单点登录cookie存储和拦截判断

This commit is contained in:
XinWei 2024-07-17 12:01:08 +08:00
parent e9bca69a3a
commit b14f06b8fa
6 changed files with 83 additions and 22 deletions

1
.gitignore vendored
View File

@ -73,3 +73,4 @@ functions/mock
screenshot screenshot
.firebase .firebase
sessionStore sessionStore
/yudao-sso-demo-by-code/

View File

@ -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;

View File

@ -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 + "/**");
} }
} }

View File

@ -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);

View File

@ -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;
}
}
} }

View File

@ -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';