Appearance
自定义登录页
在有些场景下,我们的账户体系可能会分多个群体,比较典型的场景为,账户分为企业内部员工和供应商。而企业内部员工一般使用企业内部统一的认证体系,而供应商的话一般使用软件系统自身的认证体系,而这种场景下就会产生需要多种登录方式的需求。
在平台内可以通过组件编辑器自定义登录页面,结合系统提供的自动化和脚本完成多种方式的认证体系。下文将讲述一个例子,供应商使用平台账号密码登录,企业内部员工可以使用账号密码登录也可使用动态令牌进行SSO登录的场景。
效果图
组件设置
使用组件编辑器搭建登录页面,具体的源码可参考功能演示应用中的【其他案例】->【多账户类型登录】,下文中提供组件核心源码进行说明讲解。该组件依赖了HTML
、织信Web运行时
、Axios网路请求库
等组件库。将组件的访问地址作为登录地址设置到管理后台的登录地址
中,即可替换系统的默认登录页。
html
<div style="background-image:url(images/bg.jpg);min-height:100vh" class="img js-fullheight">
<section class="ftco-section">
<div class="container">
<div class="row justify-content-center">
<div class="col-md-6 text-center mb-5">
<h2 class="heading-section">
登录
</h2>
</div>
</div>
<div class="row justify-content-center">
<div class="col-md-6 col-lg-4">
<div class="login-wrap p-0">
<h3 class="mb-4 text-center">
{{type == 'pwd' ? '账号密码' : '动态令牌'}}
</h3>
<div v-if="type == 'pwd'">
<div class="signin-form">
<div class="form-group">
<input v-model="userName" type="text" placeholder="用户名" required
class="form-control"></input>
</div>
<div class="form-group">
<input v-model="password" id="password-field" type="password" placeholder="密码"
required class="form-control"></input>
<span toggle="#password-field"
class="fa fa-fw fa-eye field-icon toggle-password"></span>
</div>
<div class="form-group">
<button type="button" class="form-control btn btn-primary submit px-3"
v-on:click="login">
登录
</button>
</div>
</div>
<p class="w-100 text-center">
— 其他登录方式 —
</p>
<div class="social d-flex text-center">
<a href="javascript:;" class="px-2 py-2 mr-md-1 rounded" v-on:click="switchType('sso')">
登录(SSO)
</a>
</div>
</div>
<div v-if="type=='sso'">
<div class="signin-form">
<div class="form-group">
<input v-model="code" type="text" placeholder="动态令牌" required class="form-control"
v-on:input="if($event.target.composing)return;code=$event.target.value"></input>
</div>
<div class="form-group">
<button type="button" class="form-control btn btn-primary submit px-3"
v-on:click="ssoLogin">
登录(SSO)
</button>
</div>
</div>
<div class="social d-flex text-center">
<a href="javascript:;" class="px-2 py-2 mr-md-1 rounded" v-on:click="switchType('pwd')">
返回
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
js
export default{
data(){
return{
userName: null,
password: null,
code: null,
type: 'pwd'
}
},
mounted() {
// 获取登录时的回跳地址,后续登录成功后进行回跳
const params = this.getQueryParams();
this.rdUrl = params.rdUrl || '/';
},
methods:{
// 密码登录
async login() {
const {userName, password} = this;
try {
const resp = await informatweb.callAutomatic({
automaticId: 'pwdLogin',
args:[
userName,
password,
'index'
]
});
this.loginResult(resp)
} catch(e) {
alert(e)
}
},
switchType(type) {
this.type = type;
},
// sso 登录
async ssoLogin() {
const {code} = this;
try {
const resp = await informatweb.callAutomatic({
automaticId: 'ssoLogin',
args:[
code,
'index',
]
})
this.loginResult(resp)
} catch(e) {
alert(e)
}
},
// 获取链接参数
getQueryParams() {
let params = {};
let url = window.location.search.substring(1);
let queryString = url.split("&");
queryString.forEach(param => {
let keyValue = param.split("=");
let key = decodeURIComponent(keyValue[0]);
let value = decodeURIComponent(keyValue[1]);
params[key] = value;
});
return params;
},
// 链接追加参数
addURLParam(url, param, value) {
// 如果 URL 中已经有查询参数,使用 & 否则使用 ?
let separator = url.indexOf('?') !== -1 ? '&' : '?';
// 组合新的 URL
return url + separator + param + '=' + encodeURIComponent(value);
},
// 登录成功后拼接token参数并回跳
loginResult(resp) {
const result = resp.returnValue;
if (!result.success) {
alert(`登录失败:${result.message || '未知错误'}`)
return;
}
// 通过在链接上拼接【_token】参数可以实现免密登录
window.location.href = this.addURLParam(this.rdUrl, '_token', result.token);
}
}
}
自动化设置
在登录组件的脚本中我们通过织信Web运行时
调用了pwdLogin
、ssoLogin
两个自动化。这两个自动化均只使用了代码片段来完成各自的业务逻辑。下面是具体的源码
TIP
由于组件中使用了织信Web运行时
是通过http调用的,所以自动化需要开启允许通过Http方式调用自动化
通过校验传入的账号密码是否正确来进行鉴权,鉴权成功后通过用户的ID创建Token,返回给前端页面
自动化入参
参数 | 类型 | 必填 | 描述 |
---|---|---|---|
userName | String | 是 | 用户名 |
password | String | 是 | 密码 |
type | String | 是 | 登录类型,一般分为PC端登录: index ,手机端登录: mobile ,也支持自定义类型,同个类型,同个账号的token会相互挤占 |
代码片段
js
const userName = automatic.getVar('userName');
const password = automatic.getVar('password');
const type = automatic.getVar('type');
var accountList = informat.system.queryAccountList({
filter: {
conditionList: [{ 'fieldId': 'userName', 'opt': 'eq', 'value': userName }]
}
});
if(accountList.length < 1) {
informat.app.abort('账号或密码错误')
}
// 平台认证用户名密码并返回结果
var result = informat.system.validateAccount(userName, password);
if (!result) {
informat.app.abort('账号或密码错误')
} else {
// 通过用户ID创建Token
const token = informat.system.createToken(accountList[0].id, type);
automatic.setReturnValue({
success: true,
accountId: accountList[0].id,
token: token
});
}
通过校验动态令牌
表中的令牌是否存在,进行鉴权。如果存在则为有效访问,如果不存在则为无效访问。并获取动态令牌与账号的绑定关系,通过绑定用户的ID创建Token,返回给前端页面。此处为示例设计的SSO登录场景,实际SSO登录业务应与企业内部的统一授权系统对接。
动态令牌数据表
字段名 | 标识符 | 类型 |
---|---|---|
绑定用户 | user | 用户选择 |
动态令牌 | code | 单行文本 |
自动化入参
参数 | 类型 | 必填 | 描述 |
---|---|---|---|
code | String | 是 | 动态令牌 |
type | String | 是 | 登录类型,一般分为PC端登录: index ,手机端登录: mobile ,也支持自定义类型,同个类型,同个账号的token会相互挤占 |
代码片段
js
const code = automatic.getVar('code');
const type = automatic.getVar('type');
// 此处为具体的SSO登录逻辑,一般是与统一权限系统对接,并获取统一权限系统的账号,与平台账号对应起来。
// 示例中通过动态令牌与用户的绑定关系进行登录
const codeRecord = informat.table.queryList('ssoCode', {
pageSize: 1,
filter: {
conditionList: [
{
fieldId: 'code',
opt: 'eq',
value: code
}
]
}
})[0];
if(codeRecord) {
const token = informat.system.createToken(codeRecord.user.id, type);
automatic.setReturnValue({
success: true,
accountId: codeRecord.user.id,
token: token
});
} else {
automatic.setReturnValue({
success: false,
message: '令牌错误'
});
}