Oauth2单点登录 vue前后端分离实现
Oauth2+Vue实现前后端分离,多域名下的单点登录。
Oauth2单点登录流程实现
oauth2-demo
介绍
这是一个基于spring cloud oauth2和vue实现的前后端分离的单点登录示例。
最后附上示例的代码实现。
后端服务
auth-server 认证服务 ,对应域名:auth.szile.com
auth-client 资源服务,对应域名:client.szile.com
角色
浏览器:客户端角色(也可以将两个域名理解为客户端角色)
auth-client:资源服务角色
auth-server: 认证服务角色
认证流程如下图:
详细介绍
首先,在client.szile.com域名下访问页面,请求一个需要登录才能访问的接口/data,资源服务判断当前未登录,返回自定义的code: 40101,表示当前未登录需要进行登录。
前端项目拦截该40101,请求/toLogin接口。
前端拦截代码:
if (data && data.code && data.code === '40101') {
return Promise.resolve(data).then(() => {
const modeUrl = router.mode === 'hash' ? "/#" : ''
const redirectUrl = process.env.VUE_APP_PUBLIC_PATH + modeUrl + router.currentRoute.path
/**
* /toLogin是Client配置的security.oauth2.sso.loginPath的值
* redirect是配置SsoSecurityConfigurer.targetUrlParameter的值, <strong>这里是登录后能回到原来页面的关键</strong>。
*/
service({
url: '/toLogin',
method: 'get',
// header的Accept不能包含application/json
headers: { 'Accept': 'text/html,application/xhtml+xml,application/xml,text/plain,*/*' },
params: { redirect: redirectUrl }
})
})
}
为什么请求/toLogin?是根据security.oauth2.sso.login-path配置的。
security:
oauth2:
sso:
# 设置登录的路径
login-path: /toLogin
请求/toLogin接口返回status:302 Location:http://oauth.szile.com/oauth/authorize?client_id=auth-client&redirect_uri=http://client.szile.com/toLogin?redirect%3D%252Fview%252F%2523%252Fauthclientpage&response_type=code&scope=read&state=7sM9yf。浏览器会根据响应请求http://oauth.szile.com/oauth/authorize接口,携带参数,请求认证服务进行授权,授权方式为code, 授权码方式。
浏览器重定向请求http://oauth.szile.com/oauth/authorize接口,认证服务接收到请求,判断当前是未登录状态,返回自定义code: 40155555 和 loginPageUrl参数,loginPageUrl=/view/#/authserverlogin。
前端拦截code: 40155555。获取loginPageUrl参数,将用户引导到登录页。
前端拦截代码:
if (data && data.code && data.code === "40155555") {
window.open(data.data.loginPageUrl, '_self')
return Promise.resolve(data)
}
用户输入用户名和密码调用/doLogin接口进行登录。登录成功后,/doLogin接口返回status:302 Location:http://oauth.szile.com/oauth/authorize?client_id=auth-client&redirect_uri=http://client.szile.com/toLogin?redirect%3D%252Fview%252F%2523%252Fauthclientpage&response_type=code&scope=read&state=7sM9yf。
浏览器接收到302,请求http://oauth.szile.com/oauth/authorize?client_id=auth-client&redirect_uri=http://client.szile.com/toLogin?redirect%3D%252Fview%252F%2523%252Fauthclientpage&response_type=code&scope=read&state=7sM9yf,即再次请求认证服务进行授权。
认证服务接收到/oauth/authorize请求,由于我配置的是自动授权,所以这里没有用户授权页面,返回status:302 Location:http://client.szile.com/toLogin?redirect=%2Fview%2F%23%2Fauthclientpage&code=ts7ATv&state=7sM9yf 。 可以看到返回了code=ts7ATv,这个code就是授权码。
浏览器接收到302,请求http://client.szile.com/toLogin?redirect=%2Fview%2F%23%2Fauthclientpage&code=ts7ATv&state=7sM9yf ,这次请求/toLogin接口不一样的是携带了授权码信息。
资源服务接收到/toLogin接口和携带的授权码信息,然后携带请求任务服务的/oauth/token接口请求token,获取到token后,向响应/toLogin接口并携带了targetUrl参数,targetUrl=http://client.szile.com/view/#/authclientpage。
需要知道的是这个响应信息会被浏览器认为是/doLogin的响应,因为是/doLogin 302重定向 到/oauth/authorize 然后有重定向到/toLogin。所以前端在/doLogin接口的响应处拦截targetUrl参数,重新回到http://client.szile.com/view/#/authclientpage 页面。这正是最初发起请求的页面。
doLogin(this.loginForm)
.then((res) => {
location.href = res.data.targetUrl;
})
.catch((err) => {
console.log(err);
});
示例代码:szile/oauth2-demo
更多推荐
所有评论(0)