单点登录cookie存储和拦截判断
This commit is contained in:
parent
e9bca69a3a
commit
b14f06b8fa
1
.gitignore
vendored
1
.gitignore
vendored
@ -73,3 +73,4 @@ functions/mock
|
||||
screenshot
|
||||
.firebase
|
||||
sessionStore
|
||||
/yudao-sso-demo-by-code/
|
||||
|
@ -42,7 +42,8 @@ public class PermissionInterceptor implements AsyncHandlerInterceptor {
|
||||
|
||||
if (needLogin) {
|
||||
XxlJobUser loginUser = loginService.ifLogin(request, response);
|
||||
if (loginUser == null) {
|
||||
Boolean authorState = loginService.ifAuthorizedLogin(request, response);
|
||||
if (loginUser == null || !authorState) {
|
||||
response.setStatus(302);
|
||||
response.setHeader("location", request.getContextPath()+"/toLogin");
|
||||
return false;
|
||||
|
@ -1,5 +1,6 @@
|
||||
package com.xxl.job.admin.controller.interceptor;
|
||||
|
||||
import com.xxl.job.admin.enums.ApiConstants;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
@ -21,8 +22,8 @@ public class WebMvcConfig implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
registry.addInterceptor(permissionInterceptor).addPathPatterns("/**");
|
||||
registry.addInterceptor(cookieInterceptor).addPathPatterns("/**");
|
||||
registry.addInterceptor(permissionInterceptor).addPathPatterns("/**").excludePathPatterns("/auth/login-by-code", "/auth/refresh-token", "/auth/logout", ApiConstants.PREFIX + "/**");
|
||||
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 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);
|
||||
if (domain != null) {
|
||||
cookie.setDomain(domain);
|
||||
|
@ -1,13 +1,23 @@
|
||||
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.util.CookieUtil;
|
||||
import com.xxl.job.admin.core.util.I18nUtil;
|
||||
import com.xxl.job.admin.core.util.JacksonUtil;
|
||||
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 org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||
import org.springframework.util.DigestUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@ -21,17 +31,21 @@ import java.math.BigInteger;
|
||||
public class LoginService {
|
||||
|
||||
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
|
||||
private XxlJobUserDao xxlJobUserDao;
|
||||
|
||||
|
||||
private String makeToken(XxlJobUser xxlJobUser){
|
||||
private String makeToken(XxlJobUser xxlJobUser) {
|
||||
String tokenJson = JacksonUtil.writeValueAsString(xxlJobUser);
|
||||
String tokenHex = new BigInteger(tokenJson.getBytes()).toString(16);
|
||||
return tokenHex;
|
||||
}
|
||||
private XxlJobUser parseToken(String tokenHex){
|
||||
|
||||
private XxlJobUser parseToken(String tokenHex) {
|
||||
XxlJobUser xxlJobUser = null;
|
||||
if (tokenHex != null) {
|
||||
String tokenJson = new String(new BigInteger(tokenHex, 16).toByteArray()); // username_password(md5)
|
||||
@ -41,10 +55,10 @@ public class LoginService {
|
||||
}
|
||||
|
||||
|
||||
public ReturnT<String> login(HttpServletRequest request, HttpServletResponse response, String username, String password, boolean ifRemember){
|
||||
public ReturnT<String> login(HttpServletRequest request, HttpServletResponse response, String username, String password, boolean ifRemember) {
|
||||
|
||||
// param
|
||||
if (username==null || username.trim().length()==0 || password==null || password.trim().length()==0){
|
||||
if (username == null || username.trim().length() == 0 || password == null || password.trim().length() == 0) {
|
||||
return new ReturnT<String>(500, I18nUtil.getString("login_param_empty"));
|
||||
}
|
||||
|
||||
@ -71,7 +85,7 @@ public class LoginService {
|
||||
* @param request
|
||||
* @param response
|
||||
*/
|
||||
public ReturnT<String> logout(HttpServletRequest request, HttpServletResponse response){
|
||||
public ReturnT<String> logout(HttpServletRequest request, HttpServletResponse response) {
|
||||
CookieUtil.remove(request, response, LOGIN_IDENTITY_KEY);
|
||||
return ReturnT.SUCCESS;
|
||||
}
|
||||
@ -82,7 +96,7 @@ public class LoginService {
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
public XxlJobUser ifLogin(HttpServletRequest request, HttpServletResponse response){
|
||||
public XxlJobUser ifLogin(HttpServletRequest request, HttpServletResponse response) {
|
||||
|
||||
// String cookieToken = CookieUtil.getValue(request, LOGIN_IDENTITY_KEY);
|
||||
// if (cookieToken != null) {
|
||||
@ -112,4 +126,49 @@ public class LoginService {
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
// 获取 URL 中的查询参数
|
||||
@ -67,10 +71,10 @@
|
||||
// 提交
|
||||
const redirectUri = 'http://127.0.0.1:9090/xxl-job-admin/toLogin'; // 需要修改成,你回调的地址,就是在 index.html 拼接的 redirectUri
|
||||
$.ajax({
|
||||
url: "http://127.0.0.1:9090/xxl-job-admin/auth/login-by-code?code=" + code
|
||||
url: "http://127.0.0.1:9090/xxl-job-admin/auth/login-by-code?code=" + code
|
||||
+ '&redirectUri=' + redirectUri,
|
||||
method: 'POST',
|
||||
success: function( result ) {
|
||||
success: function (result) {
|
||||
if (result.code !== 0) {
|
||||
// layer.open({
|
||||
// title: I18n.system_tips,
|
||||
@ -81,20 +85,15 @@
|
||||
alert('获得访问令牌失败,原因:' + result.msg)
|
||||
return;
|
||||
}
|
||||
// 设置到 localStorage 中
|
||||
localStorage.setItem('ACCESS-TOKEN', result.data.access_token);
|
||||
localStorage.setItem('REFRESH-TOKEN', result.data.refresh_token);
|
||||
localStorage.setItem('EXPIRES-IN', Date.now() + result.data.expires_in * 1000);
|
||||
// 设置cookie
|
||||
document.cookie = "ACCESS_TOKEN=" + result.data.access_token + "; max-age=" + result.data.expires_in + "; path=/xxl-job-admin";
|
||||
document.cookie = "REFRESH_TOKEN=" + result.data.refresh_token + "; max-age=43000; path=/xxl-job-admin";
|
||||
// 跳转回首页
|
||||
window.location.href = '/xxl-job-admin';
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
// 情况二:Token失效(暂未实现)
|
||||
else if (Date.now() > localStorage.getItem('EXPIRES-IN')) {
|
||||
console.log('重新获取授权码')
|
||||
}
|
||||
// 情况三:已登录
|
||||
else {
|
||||
window.location.href = '/xxl-job-admin';
|
||||
|
Loading…
Reference in New Issue
Block a user