单点登录cookie存储和拦截判断
This commit is contained in:
parent
e9bca69a3a
commit
b14f06b8fa
1
.gitignore
vendored
1
.gitignore
vendored
@ -73,3 +73,4 @@ functions/mock
|
|||||||
screenshot
|
screenshot
|
||||||
.firebase
|
.firebase
|
||||||
sessionStore
|
sessionStore
|
||||||
|
/yudao-sso-demo-by-code/
|
||||||
|
@ -42,7 +42,8 @@ public class PermissionInterceptor implements AsyncHandlerInterceptor {
|
|||||||
|
|
||||||
if (needLogin) {
|
if (needLogin) {
|
||||||
XxlJobUser loginUser = loginService.ifLogin(request, response);
|
XxlJobUser loginUser = loginService.ifLogin(request, response);
|
||||||
if (loginUser == null) {
|
Boolean authorState = loginService.ifAuthorizedLogin(request, response);
|
||||||
|
if (loginUser == null || !authorState) {
|
||||||
response.setStatus(302);
|
response.setStatus(302);
|
||||||
response.setHeader("location", request.getContextPath()+"/toLogin");
|
response.setHeader("location", request.getContextPath()+"/toLogin");
|
||||||
return false;
|
return false;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.xxl.job.admin.controller.interceptor;
|
package com.xxl.job.admin.controller.interceptor;
|
||||||
|
|
||||||
|
import com.xxl.job.admin.enums.ApiConstants;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
@ -21,8 +22,8 @@ public class WebMvcConfig implements WebMvcConfigurer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addInterceptors(InterceptorRegistry registry) {
|
public void addInterceptors(InterceptorRegistry registry) {
|
||||||
registry.addInterceptor(permissionInterceptor).addPathPatterns("/**");
|
registry.addInterceptor(permissionInterceptor).addPathPatterns("/**").excludePathPatterns("/auth/login-by-code", "/auth/refresh-token", "/auth/logout", ApiConstants.PREFIX + "/**");
|
||||||
registry.addInterceptor(cookieInterceptor).addPathPatterns("/**");
|
registry.addInterceptor(cookieInterceptor).addPathPatterns("/**").excludePathPatterns("/auth/login-by-code", "/auth/refresh-token", "/auth/logout", ApiConstants.PREFIX + "/**");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -37,7 +37,7 @@ public class CookieUtil {
|
|||||||
* @param value
|
* @param value
|
||||||
* @param maxAge
|
* @param maxAge
|
||||||
*/
|
*/
|
||||||
private static void set(HttpServletResponse response, String key, String value, String domain, String path, int maxAge, boolean isHttpOnly) {
|
public static void set(HttpServletResponse response, String key, String value, String domain, String path, int maxAge, boolean isHttpOnly) {
|
||||||
Cookie cookie = new Cookie(key, value);
|
Cookie cookie = new Cookie(key, value);
|
||||||
if (domain != null) {
|
if (domain != null) {
|
||||||
cookie.setDomain(domain);
|
cookie.setDomain(domain);
|
||||||
|
@ -1,13 +1,23 @@
|
|||||||
package com.xxl.job.admin.service;
|
package com.xxl.job.admin.service;
|
||||||
|
|
||||||
|
import com.xxl.job.admin.client.OAuth2Client;
|
||||||
|
import com.xxl.job.admin.client.dto.CommonResult;
|
||||||
|
import com.xxl.job.admin.client.dto.oauth2.OAuth2AccessTokenRespDTO;
|
||||||
|
import com.xxl.job.admin.client.dto.oauth2.OAuth2CheckTokenRespDTO;
|
||||||
import com.xxl.job.admin.core.model.XxlJobUser;
|
import com.xxl.job.admin.core.model.XxlJobUser;
|
||||||
import com.xxl.job.admin.core.util.CookieUtil;
|
import com.xxl.job.admin.core.util.CookieUtil;
|
||||||
import com.xxl.job.admin.core.util.I18nUtil;
|
import com.xxl.job.admin.core.util.I18nUtil;
|
||||||
import com.xxl.job.admin.core.util.JacksonUtil;
|
import com.xxl.job.admin.core.util.JacksonUtil;
|
||||||
import com.xxl.job.admin.dao.XxlJobUserDao;
|
import com.xxl.job.admin.dao.XxlJobUserDao;
|
||||||
|
import com.xxl.job.admin.framework.security.core.LoginUser;
|
||||||
|
import com.xxl.job.admin.framework.security.core.filter.TokenAuthenticationFilter;
|
||||||
|
import com.xxl.job.admin.framework.security.core.handler.AccessDeniedHandlerImpl;
|
||||||
|
import com.xxl.job.admin.framework.security.core.util.SecurityUtils;
|
||||||
import com.xxl.job.core.biz.model.ReturnT;
|
import com.xxl.job.core.biz.model.ReturnT;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||||
import org.springframework.util.DigestUtils;
|
import org.springframework.util.DigestUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
@ -21,7 +31,10 @@ import java.math.BigInteger;
|
|||||||
public class LoginService {
|
public class LoginService {
|
||||||
|
|
||||||
public static final String LOGIN_IDENTITY_KEY = "XXL_JOB_LOGIN_IDENTITY";
|
public static final String LOGIN_IDENTITY_KEY = "XXL_JOB_LOGIN_IDENTITY";
|
||||||
|
public static final String ACCESS_TOKEN = "ACCESS_TOKEN";
|
||||||
|
public static final String REFRESH_TOKEN = "REFRESH_TOKEN";
|
||||||
|
@Resource
|
||||||
|
private OAuth2Client oauth2Client;
|
||||||
@Resource
|
@Resource
|
||||||
private XxlJobUserDao xxlJobUserDao;
|
private XxlJobUserDao xxlJobUserDao;
|
||||||
|
|
||||||
@ -31,6 +44,7 @@ public class LoginService {
|
|||||||
String tokenHex = new BigInteger(tokenJson.getBytes()).toString(16);
|
String tokenHex = new BigInteger(tokenJson.getBytes()).toString(16);
|
||||||
return tokenHex;
|
return tokenHex;
|
||||||
}
|
}
|
||||||
|
|
||||||
private XxlJobUser parseToken(String tokenHex) {
|
private XxlJobUser parseToken(String tokenHex) {
|
||||||
XxlJobUser xxlJobUser = null;
|
XxlJobUser xxlJobUser = null;
|
||||||
if (tokenHex != null) {
|
if (tokenHex != null) {
|
||||||
@ -112,4 +126,49 @@ public class LoginService {
|
|||||||
return test;
|
return test;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断是否登录授权
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* @param response
|
||||||
|
* @return java.lang.Boolean
|
||||||
|
*/
|
||||||
|
public Boolean ifAuthorizedLogin(HttpServletRequest request, HttpServletResponse response) {
|
||||||
|
String accessToken = CookieUtil.getValue(request, ACCESS_TOKEN);
|
||||||
|
String refreshToken = CookieUtil.getValue(request, REFRESH_TOKEN);
|
||||||
|
// 如果未登录授权过
|
||||||
|
if (accessToken == null && refreshToken == null) {
|
||||||
|
// 登录授权 需要跳转登录授权页面
|
||||||
|
// 基于 token 构建登录用户
|
||||||
|
LoginUser loginUser = buildLoginUserByToken(accessToken);
|
||||||
|
// 设置当前用户
|
||||||
|
if (loginUser != null) {
|
||||||
|
SecurityUtils.setLoginUser(loginUser, request);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} else if (accessToken == null) {
|
||||||
|
// 刷新令牌 不需要跳转登录授权页面
|
||||||
|
OAuth2AccessTokenRespDTO refreshData = oauth2Client.refreshToken(refreshToken).getData();
|
||||||
|
CookieUtil.set(response, ACCESS_TOKEN, refreshData.getAccessToken(), null, "/xxl-job-admin", refreshData.getExpiresIn().intValue(), true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// 令牌未过期不需要重新登录
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
private LoginUser buildLoginUserByToken(String token) {
|
||||||
|
try {
|
||||||
|
CommonResult<OAuth2CheckTokenRespDTO> accessTokenResult = oauth2Client.checkToken(token);
|
||||||
|
OAuth2CheckTokenRespDTO accessToken = accessTokenResult.getData();
|
||||||
|
if (accessToken == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// 构建登录用户
|
||||||
|
return new LoginUser().setId(accessToken.getUserId()).setUserType(accessToken.getUserType())
|
||||||
|
.setTenantId(accessToken.getTenantId()).setScopes(accessToken.getScopes())
|
||||||
|
.setAccessToken(accessToken.getAccessToken());
|
||||||
|
} catch (Exception exception) {
|
||||||
|
// 校验 Token 不通过时,考虑到一些接口是无需登录的,所以直接返回 null 即可
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,7 +54,11 @@
|
|||||||
+ '&response_type=' + responseType;
|
+ '&response_type=' + responseType;
|
||||||
}
|
}
|
||||||
|
|
||||||
const accessToken = localStorage.getItem('ACCESS-TOKEN');
|
// 读取 cookie
|
||||||
|
const accessToken = document.cookie
|
||||||
|
.replace(/(?:(?:^|.*;\s*)ACCESS_TOKEN\s*\=\s*([^;]*).*$)|^.*$/, "$1");
|
||||||
|
const refreshToken = document.cookie
|
||||||
|
.replace(/(?:(?:^|.*;\s*)REFRESH_TOKEN\s*\=\s*([^;]*).*$)|^.*$/, "$1");
|
||||||
// 情况一:未登录
|
// 情况一:未登录
|
||||||
if (!accessToken) {
|
if (!accessToken) {
|
||||||
// 获取 URL 中的查询参数
|
// 获取 URL 中的查询参数
|
||||||
@ -81,20 +85,15 @@
|
|||||||
alert('获得访问令牌失败,原因:' + result.msg)
|
alert('获得访问令牌失败,原因:' + result.msg)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 设置到 localStorage 中
|
// 设置cookie
|
||||||
localStorage.setItem('ACCESS-TOKEN', result.data.access_token);
|
document.cookie = "ACCESS_TOKEN=" + result.data.access_token + "; max-age=" + result.data.expires_in + "; path=/xxl-job-admin";
|
||||||
localStorage.setItem('REFRESH-TOKEN', result.data.refresh_token);
|
document.cookie = "REFRESH_TOKEN=" + result.data.refresh_token + "; max-age=43000; path=/xxl-job-admin";
|
||||||
localStorage.setItem('EXPIRES-IN', Date.now() + result.data.expires_in * 1000);
|
|
||||||
// 跳转回首页
|
// 跳转回首页
|
||||||
window.location.href = '/xxl-job-admin';
|
window.location.href = '/xxl-job-admin';
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 情况二:Token失效(暂未实现)
|
|
||||||
else if (Date.now() > localStorage.getItem('EXPIRES-IN')) {
|
|
||||||
console.log('重新获取授权码')
|
|
||||||
}
|
|
||||||
// 情况三:已登录
|
// 情况三:已登录
|
||||||
else {
|
else {
|
||||||
window.location.href = '/xxl-job-admin';
|
window.location.href = '/xxl-job-admin';
|
||||||
|
Loading…
Reference in New Issue
Block a user