背景:
现在有一个需求是客户要求使用oauth2.0方式的单点登录进入系统,原先我们都是使用cas方式的单点登录。这里整理下代码:
1.oauth2.0
分为4个步骤:
- 获取第三方token。
为了安全性(不暴露第三方token和secretKey),c此处是后端对第三方提供的API进行处理,前端只去公司后端提供的接口中拿token。 - 拿到第三方token后,跳转到第三方认证平台。
- 跳转到第三方认证平台后,第三方平台在URL地址栏中携带ticket票据返回。
- 从地址栏中拿到票据,绑定用户信息。
拿到token后要把token保存到缓存中,在绑定用户信息时使用。
permission.js中代码实现:
if (window.g.OAUTH_URL) {
if (window.g.OAUTH_URL && !window.location.search) {
let oauthToken = ''
getOauthToken().then((res) => {
if (res.data.status) {
// 1.获取token
if (res.data.data.content) {
oauthToken = res.data.data.content.token
// 2.跳转到认证平台,不可以写在异步获取token的函数外面
window.location.href = window.g.OAUTH_URL + `/unified_identity_logon/#/login?pcToken=${oauthToken}&applicationCode=${window.$oauthCmccr}`
localStorage.setItem('Oauth_Token', oauthToken)
}
}
})
} else {
// axios.get(`${window.g.OAUTH_URL}/unified_identity_logon/#/login?ticket=${window.location.search.split('=')[1]}`).then(res => {})
// 3.认证平台跳回,并在地址栏包含ticket,获取ticket
// const ticket = window.location.search.split('=')[1]
var reg = new RegExp('ticket' + '=([^&]*)(&|$)', 'i') // /ticket=([^&]*)(&|$)/i
var ticket = window.location.search.substr(1).match(reg)[1]
// 4.获取用户信息
const token = localStorage.getItem('Oauth_Token')
getOauthUserInfo(ticket, token).then((res) => {
if (res.data.status && res.data.content.hasOwnProperty('userId')) {
const username = res.data.content.userId
if (username) {
// 5.绑定
casBind(ticket, username).then(res => {
if (res.data.code === 0) {
axios.get(`${window.g.BASE_CCR}/oauth/token?client_id=xxxxx&client_secret=xxxxx&grant_type=password&username=${username}&password=${ticket}`).then(response => {
//token和刷新token存到缓存中,各端保持登陆状态
setToken(response.data.access_token, res.data.expires_in)
setRefreshToken(response.data.refresh_token)
autoGetToken(response.data.refresh_token)
window.location.search = ''
next('/')
}).catch(() => {
Message({
type: 'error',
message: '登录失败'
})
// 登陆失败再次跳到认证中心
window.location.href = window.g.OAUTH_URL + `/unified_identity_logon/#/login?pcToken=${token}&applicationCode=${window.$oauthCmccr}`
})
}
}).catch(() => {
next()
})
} else {
Message({
type: 'error',
message: '登录超时'
})
window.location.href = window.g.OAUTH_URL + `/unified_identity_logon/#/login?pcToken=${token}&applicationCode=${window.$oauthCmccr}`
}
}
})
}
}
在main.js中请求后端接口拿到登录地址。
axios.get(window.g.BASE_CCR + '/center/xxx/v1/xxxx/xxxxx').then(res => {
if (res.data.code === 0) {
var data = JSON.parse(res.data.data)
// 应用码
window.$oauthCmccr = data.userConfig.oauthCmccr
// cas方式
if (data.userConfig.authType === 'cas') {
window.g.CAS_URL = data.userConfig.casLoginUrl || ''
window.g.CAS_LOGOUT = data.userConfig.casLogout || ''
} else {
// oauth2.0方式
window.g.OAUTH_URL = data.userConfig.oauthLoginUrl || ''
// window.g.OAUTH_LOGOUT = data.userConfig.casLogout || ''
}
} else {
Message({
type: 'error',
message: '配置信息获取失败'
})
}