From a646cb67ce4419b7ed50ea823e11e0b40ed9b9ba Mon Sep 17 00:00:00 2001 From: fengshuonan Date: Sun, 27 Dec 2020 17:33:08 +0800 Subject: [PATCH] =?UTF-8?q?=E3=80=90auth=E3=80=91=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E5=88=9B=E5=BB=BAsession=E4=BC=9A=E5=86=99cookie=E7=9A=84?= =?UTF-8?q?=E5=8A=9F=E8=83=BD=EF=BC=8C=E5=A2=9E=E5=8A=A0systemConfig?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../roses/kernel/auth/api/AuthServiceApi.java | 8 +-- .../roses/kernel/auth/api/LoginUserApi.java | 9 ++++ .../kernel/auth/api/PermissionServiceApi.java | 2 +- .../auth/api/cookie/SessionCookieCreator.java | 43 ++++++++++++++++ .../auth/api/expander/AuthConfigExpander.java | 30 +++++++++++- .../roses/kernel/auth/auth/LoginUserImpl.java | 36 +++++++++++++- .../auth/session/DefaultSessionManager.java | 37 +++++++++++++- .../cookie/DefaultSessionCookieCreator.java | 23 +++++++++ .../starter/GunsAuthAutoConfiguration.java | 15 +++++- .../system/constants/SymbolConstant.java | 49 ------------------- .../system/constants/SystemConstants.java | 15 ++++++ .../system/expander/SystemConfigExpander.java | 44 +++++++++++++++++ 12 files changed, 249 insertions(+), 62 deletions(-) create mode 100644 kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/cookie/SessionCookieCreator.java create mode 100644 kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/cookie/DefaultSessionCookieCreator.java create mode 100644 kernel-s-system/system-api/src/main/java/cn/stylefeng/roses/kernel/system/expander/SystemConfigExpander.java diff --git a/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/AuthServiceApi.java b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/AuthServiceApi.java index 1f4e1a87e..a9c7422e3 100644 --- a/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/AuthServiceApi.java +++ b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/AuthServiceApi.java @@ -69,13 +69,7 @@ public interface AuthServiceApi { boolean getTokenFlag(String token); /** - * 校验用户访问的url是否认证通过 - *

- * 校验会进行两方面: - *

- * 第一,校验用户的token是否过期 - *

- * 第二,校验用户的session是否失效,但是记住我的session失效后会自动创建session,直到jwt失效后 + * 校验用户是否认证通过,认证是校验token的过程,校验失败会抛出异常 * * @param token 用户登陆的token * @param requestUrl 被校验的url diff --git a/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/LoginUserApi.java b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/LoginUserApi.java index 0b8896274..14735754d 100644 --- a/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/LoginUserApi.java +++ b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/LoginUserApi.java @@ -54,4 +54,13 @@ public interface LoginUserApi { */ boolean getSuperAdminFlag(); + /** + * 判断当前用户是否登录 + * + * @return 是否登录,true是,false否 + * @author fengshuonan + * @date 2020/10/17 11:02 + */ + boolean hasLogin(); + } diff --git a/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/PermissionServiceApi.java b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/PermissionServiceApi.java index 94837be86..f20100f30 100644 --- a/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/PermissionServiceApi.java +++ b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/PermissionServiceApi.java @@ -13,7 +13,7 @@ public interface PermissionServiceApi { /** * 校验当前用户是否有某个接口的权限 *

- * 只要认证不通过,则会抛出异常 + * 只要权限校验不通过,则会抛出异常 * * @param token 用户登陆的token * @param requestUrl 被校验的url diff --git a/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/cookie/SessionCookieCreator.java b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/cookie/SessionCookieCreator.java new file mode 100644 index 000000000..a3b567c56 --- /dev/null +++ b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/cookie/SessionCookieCreator.java @@ -0,0 +1,43 @@ +package cn.stylefeng.roses.kernel.auth.api.cookie; + +import cn.hutool.core.convert.Convert; + +import javax.servlet.http.Cookie; + +/** + * cookie的创建器,用在session创建时,给httpServletResponse添加cookie + *

+ * 每个公司情况不一样,所以预留拓展接口 + * + * @author fengshuonan + * @date 2020/12/27 13:28 + */ +public abstract class SessionCookieCreator { + + /** + * 创建cookie的操作 + *

+ * 这里不要重写这个方法,重写后名称对不上可能导致登录后权限校验失败 + * + * @param cookieName cookie的名称 + * @param cookieValue cookie的值 + * @param sessionExpiredSeconds cookie过期时间 + * @author fengshuonan + * @date 2020/12/27 13:29 + */ + public Cookie createCookie(String cookieName, String cookieValue, Integer sessionExpiredSeconds) { + Cookie cookie = new Cookie(cookieName, cookieValue); + cookie.setMaxAge(Convert.toInt(sessionExpiredSeconds)); + this.expandCookieProp(cookie); + return cookie; + } + + /** + * 拓展cookie的配置 + * + * @author fengshuonan + * @date 2020/12/27 13:41 + */ + public abstract void expandCookieProp(Cookie cookie); + +} diff --git a/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/expander/AuthConfigExpander.java b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/expander/AuthConfigExpander.java index a2fb9fd7d..79a8575c7 100644 --- a/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/expander/AuthConfigExpander.java +++ b/kernel-d-auth/auth-api/src/main/java/cn/stylefeng/roses/kernel/auth/api/expander/AuthConfigExpander.java @@ -69,7 +69,7 @@ public class AuthConfigExpander { } /** - * 获取携带token的header头的名称 + * 获取携带token的param传参的名称 * * @author fengshuonan * @date 2020/10/22 14:11 @@ -88,4 +88,32 @@ public class AuthConfigExpander { return ConfigContext.me().getSysConfigValueWithDefault("SYS_DEFAULT_PASSWORD", String.class, DEFAULT_PASSWORD); } + /** + * 会话信息是否增加保存在 cookie 中 + *

+ * 如果开启此开关,会发生两件事: + *

+ * 1.则登录过程中创建会话时,会HttpServletResponse对象进行addCookie()操作 + *

+ * 2.获取当前用户token会多一个从cookie中获取token这个方式 + *

+ * 一般这个开关的开启,用在单体不分离的版本中 + * + * @author fengshuonan + * @date 2020/12/27 13:15 + */ + public static Boolean getSessionAddToCookie() { + return ConfigContext.me().getSysConfigValueWithDefault("SYS_SESSION_ADD_TO_COOKIE", Boolean.class, Boolean.FALSE); + } + + /** + * 会话保存在cookie中时,cooke的name + * + * @author fengshuonan + * @date 2020/12/27 13:18 + */ + public static String getSessionCookieName() { + return ConfigContext.me().getSysConfigValueWithDefault("SYS_SESSION_COOKIE_NAME", String.class, DEFAULT_AUTH_HEADER_NAME); + } + } diff --git a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/LoginUserImpl.java b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/LoginUserImpl.java index 5522af927..5db68ffbc 100644 --- a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/LoginUserImpl.java +++ b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/auth/LoginUserImpl.java @@ -10,6 +10,7 @@ import cn.stylefeng.roses.kernel.rule.util.HttpServletUtil; import org.springframework.stereotype.Service; import javax.annotation.Resource; +import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import static cn.stylefeng.roses.kernel.auth.api.exception.enums.AuthExceptionEnum.TOKEN_GET_ERROR; @@ -32,7 +33,7 @@ public class LoginUserImpl implements LoginUserApi { // 获取当前http请求 HttpServletRequest request = HttpServletUtil.getRequest(); - // 优先从param参数中获取token + // 1. 优先从param参数中获取token String parameterToken = request.getParameter(AuthConfigExpander.getAuthTokenParamName()); // 不为空则直接返回param的token @@ -40,12 +41,28 @@ public class LoginUserImpl implements LoginUserApi { return parameterToken; } - // 从header中获取token + // 2. 从header中获取token String authToken = request.getHeader(AuthConfigExpander.getAuthTokenHeaderName()); if (StrUtil.isNotBlank(authToken)) { return authToken; } + // 3. 从cookie中获取token + if (AuthConfigExpander.getSessionAddToCookie()) { + String sessionCookieName = AuthConfigExpander.getSessionCookieName(); + Cookie[] cookies = request.getCookies(); + if (cookies != null && cookies.length > 0) { + for (Cookie cookie : cookies) { + + // 如果cookie有对应的值,并且不为空 + if (sessionCookieName.equals(cookie.getName()) + && StrUtil.isNotBlank(cookie.getValue())) { + return cookie.getValue(); + } + } + } + } + // 获取不到token,直接告诉用户 throw new AuthException(TOKEN_GET_ERROR); } @@ -89,4 +106,19 @@ public class LoginUserImpl implements LoginUserApi { return loginUser.getSuperAdmin(); } + @Override + public boolean hasLogin() { + + // 获取用户的token + String token = null; + try { + token = getToken(); + } catch (Exception e) { + return false; + } + + // 获取是否在会话中有 + return sessionManagerApi.haveSession(token); + } + } diff --git a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/DefaultSessionManager.java b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/DefaultSessionManager.java index e051e5523..75ddea429 100644 --- a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/DefaultSessionManager.java +++ b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/DefaultSessionManager.java @@ -1,9 +1,15 @@ package cn.stylefeng.roses.kernel.auth.session; +import cn.hutool.core.convert.Convert; import cn.stylefeng.roses.kernel.auth.api.SessionManagerApi; +import cn.stylefeng.roses.kernel.auth.api.cookie.SessionCookieCreator; +import cn.stylefeng.roses.kernel.auth.api.expander.AuthConfigExpander; import cn.stylefeng.roses.kernel.auth.api.pojo.login.LoginUser; import cn.stylefeng.roses.kernel.cache.api.CacheOperatorApi; +import cn.stylefeng.roses.kernel.rule.util.HttpServletUtil; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletResponse; import java.util.HashSet; import java.util.Set; @@ -38,10 +44,19 @@ public class DefaultSessionManager implements SessionManagerApi { */ private final Long sessionExpiredSeconds; - public DefaultSessionManager(CacheOperatorApi loginUserCache, CacheOperatorApi> allPlaceLoginTokenCache, Long sessionExpiredSeconds) { + /** + * cookie的创建器,用在session创建时,给response添加cookie + */ + private final SessionCookieCreator sessionCookieCreator; + + public DefaultSessionManager(CacheOperatorApi loginUserCache, + CacheOperatorApi> allPlaceLoginTokenCache, + Long sessionExpiredSeconds, + SessionCookieCreator sessionCookieCreator) { this.loginUserCache = loginUserCache; this.allPlaceLoginTokenCache = allPlaceLoginTokenCache; this.sessionExpiredSeconds = sessionExpiredSeconds; + this.sessionCookieCreator = sessionCookieCreator; } @Override @@ -57,6 +72,15 @@ public class DefaultSessionManager implements SessionManagerApi { } theUserTokens.add(token); allPlaceLoginTokenCache.put(loginUser.getUserId().toString(), theUserTokens); + + // 如果开启了cookie存储会话信息,则需要给HttpServletResponse添加一个cookie + if (AuthConfigExpander.getSessionAddToCookie()) { + String sessionCookieName = AuthConfigExpander.getSessionCookieName(); + Cookie cookie = sessionCookieCreator.createCookie(sessionCookieName, token, Convert.toInt(sessionExpiredSeconds)); + HttpServletResponse response = HttpServletUtil.getResponse(); + response.addCookie(cookie); + } + } @Override @@ -77,7 +101,10 @@ public class DefaultSessionManager implements SessionManagerApi { Long userId = loginUser.getUserId(); Set userTokens = allPlaceLoginTokenCache.get(userId.toString()); if (userTokens != null) { + + // 清除对应的token的信息 userTokens.remove(token); + allPlaceLoginTokenCache.put(userId.toString(), userTokens); // 如果删除后size为0,则把整个key删掉 if (userTokens.size() == 0) { @@ -101,6 +128,14 @@ public class DefaultSessionManager implements SessionManagerApi { // 获取用户id Long userId = session.getUserId(); + // 获取这个用户多余的几个登录信息 + Set thisUserTokens = allPlaceLoginTokenCache.get(userId.toString()); + for (String thisUserToken : thisUserTokens) { + if (!thisUserToken.equals(token)) { + loginUserCache.remove(thisUserToken); + } + } + // 设置用户id对应的token列表为参数token HashSet tokenSet = new HashSet<>(); tokenSet.add(token); diff --git a/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/cookie/DefaultSessionCookieCreator.java b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/cookie/DefaultSessionCookieCreator.java new file mode 100644 index 000000000..fc5ea64ad --- /dev/null +++ b/kernel-d-auth/auth-sdk/src/main/java/cn/stylefeng/roses/kernel/auth/session/cookie/DefaultSessionCookieCreator.java @@ -0,0 +1,23 @@ +package cn.stylefeng.roses.kernel.auth.session.cookie; + +import cn.stylefeng.roses.kernel.auth.api.cookie.SessionCookieCreator; + +import javax.servlet.http.Cookie; + +/** + * 默认的cookie创建 + *

+ * 这里预留了expandCookieProp的接口可以拓展cookie的属性 + * + * @author fengshuonan + * @date 2020/12/27 13:29 + */ +public class DefaultSessionCookieCreator extends SessionCookieCreator { + + @Override + public void expandCookieProp(Cookie cookie) { + cookie.setHttpOnly(true); + cookie.setPath("/"); + } + +} diff --git a/kernel-d-auth/auth-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/auth/starter/GunsAuthAutoConfiguration.java b/kernel-d-auth/auth-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/auth/starter/GunsAuthAutoConfiguration.java index 0ebcaafdb..1583e95d5 100644 --- a/kernel-d-auth/auth-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/auth/starter/GunsAuthAutoConfiguration.java +++ b/kernel-d-auth/auth-spring-boot-starter/src/main/java/cn/stylefeng/roses/kernel/auth/starter/GunsAuthAutoConfiguration.java @@ -3,6 +3,7 @@ package cn.stylefeng.roses.kernel.auth.starter; import cn.hutool.cache.CacheUtil; import cn.hutool.cache.impl.TimedCache; import cn.stylefeng.roses.kernel.auth.api.SessionManagerApi; +import cn.stylefeng.roses.kernel.auth.api.cookie.SessionCookieCreator; import cn.stylefeng.roses.kernel.auth.api.expander.AuthConfigExpander; import cn.stylefeng.roses.kernel.auth.api.password.PasswordStoredEncryptApi; import cn.stylefeng.roses.kernel.auth.api.password.PasswordTransferEncryptApi; @@ -12,6 +13,7 @@ import cn.stylefeng.roses.kernel.auth.password.RsaPasswordTransferEncrypt; import cn.stylefeng.roses.kernel.auth.session.DefaultSessionManager; import cn.stylefeng.roses.kernel.auth.session.cache.logintoken.MemoryLoginTokenCache; import cn.stylefeng.roses.kernel.auth.session.cache.loginuser.MemoryLoginUserCache; +import cn.stylefeng.roses.kernel.auth.session.cookie.DefaultSessionCookieCreator; import cn.stylefeng.roses.kernel.cache.api.constants.CacheConstants; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; @@ -53,6 +55,17 @@ public class GunsAuthAutoConfiguration { return new RsaPasswordTransferEncrypt(publicKey, privateKey); } + /** + * session cookie的创建 + * + * @author fengshuonan + * @date 2020/12/27 15:48 + */ + @Bean + public SessionCookieCreator sessionCookieCreator() { + return new DefaultSessionCookieCreator(); + } + /** * 默认的session缓存为内存缓存,方便启动 *

@@ -72,7 +85,7 @@ public class GunsAuthAutoConfiguration { MemoryLoginUserCache memoryLoginUserCache = new MemoryLoginUserCache(loginUsers); MemoryLoginTokenCache memoryLoginTokenCache = new MemoryLoginTokenCache(loginTokens); - return new DefaultSessionManager(memoryLoginUserCache, memoryLoginTokenCache, sessionExpiredSeconds); + return new DefaultSessionManager(memoryLoginUserCache, memoryLoginTokenCache, sessionExpiredSeconds, sessionCookieCreator()); } } diff --git a/kernel-s-system/system-api/src/main/java/cn/stylefeng/roses/kernel/system/constants/SymbolConstant.java b/kernel-s-system/system-api/src/main/java/cn/stylefeng/roses/kernel/system/constants/SymbolConstant.java index e0408bf1c..835a066c8 100644 --- a/kernel-s-system/system-api/src/main/java/cn/stylefeng/roses/kernel/system/constants/SymbolConstant.java +++ b/kernel-s-system/system-api/src/main/java/cn/stylefeng/roses/kernel/system/constants/SymbolConstant.java @@ -8,59 +8,10 @@ package cn.stylefeng.roses.kernel.system.constants; */ public interface SymbolConstant { - String PERIOD = "."; - String COMMA = ","; - String COLON = ":"; - - String SEMICOLON = ";"; - - String EXCLAMATION_MARK = "!"; - - String QUESTION_MARK = "?"; - - String HYPHEN = "-"; - - String ASTERISK = "*"; - - String APOSTROPHE = "`"; - - String DASH = "-"; - - String UNDER_SCORE = "_"; - - String SINGLE_QUOTATION_MARK = "'"; - - String DOUBLE_QUOTATION_MARK = "\""; - - String LEFT_ROUND_BRACKETS = "("; - - String RIGHT_ROUND_BRACKETS = ")"; - String LEFT_SQUARE_BRACKETS = "["; String RIGHT_SQUARE_BRACKETS = "]"; - String LEFT_ANGLE_BRACKETS = "<"; - - String RIGHT_ANGLE_BRACKETS = ">"; - - String LEFT_CURLY_BRACKETS = "{"; - - String RIGHT_CURLY_BRACKETS = "}"; - - String DOLLAR = "$"; - - String PERCENT = "%"; - - String LEFT_DIVIDE = "/"; - - String RIGHT_DIVIDE = "\\"; - - String LEFT_DOUBLE_DIVIDE = "//"; - - String RIGHT_DOUBLE_DIVIDE = "\\\\"; - - String EQUAL = "="; } diff --git a/kernel-s-system/system-api/src/main/java/cn/stylefeng/roses/kernel/system/constants/SystemConstants.java b/kernel-s-system/system-api/src/main/java/cn/stylefeng/roses/kernel/system/constants/SystemConstants.java index a0b7bf74d..ec5ba030a 100644 --- a/kernel-s-system/system-api/src/main/java/cn/stylefeng/roses/kernel/system/constants/SystemConstants.java +++ b/kernel-s-system/system-api/src/main/java/cn/stylefeng/roses/kernel/system/constants/SystemConstants.java @@ -33,4 +33,19 @@ public interface SystemConstants { */ String PID_RIGHT_DIVIDE_SYMBOL = "]"; + /** + * 默认的系统版本号 + */ + String DEFAULT_SYSTEM_VERSION = "20210101"; + + /** + * 默认多租户的开关:关闭 + */ + Boolean DEFAULT_TENANT_OPEN = false; + + /** + * 默认验证码的开关:关闭 + */ + Boolean DEFAULT_CAPTCHA_OPEN = false; + } \ No newline at end of file diff --git a/kernel-s-system/system-api/src/main/java/cn/stylefeng/roses/kernel/system/expander/SystemConfigExpander.java b/kernel-s-system/system-api/src/main/java/cn/stylefeng/roses/kernel/system/expander/SystemConfigExpander.java new file mode 100644 index 000000000..3233a7cb0 --- /dev/null +++ b/kernel-s-system/system-api/src/main/java/cn/stylefeng/roses/kernel/system/expander/SystemConfigExpander.java @@ -0,0 +1,44 @@ +package cn.stylefeng.roses.kernel.system.expander; + +import cn.stylefeng.roses.kernel.config.api.context.ConfigContext; +import cn.stylefeng.roses.kernel.system.constants.SystemConstants; + +/** + * 系统的一些基础信息 + * + * @author fengshuonan + * @date 2020/12/27 17:13 + */ +public class SystemConfigExpander { + + /** + * 获取系统发布的版本号(防止css和js的缓存) + * + * @author fengshuonan + * @date 2020/12/27 17:14 + */ + public static String getReleaseVersion() { + return ConfigContext.me().getSysConfigValueWithDefault("SYS_RELEASE_VERSION", String.class, SystemConstants.DEFAULT_SYSTEM_VERSION); + } + + /** + * 获取租户是否开启的标识,默认是关的 + * + * @author fengshuonan + * @date 2020/12/27 17:21 + */ + public static Boolean getTenantOpen() { + return ConfigContext.me().getSysConfigValueWithDefault("SYS_TENANT_OPEN", Boolean.class, SystemConstants.DEFAULT_TENANT_OPEN); + } + + /** + * 获取验证码的开关 + * + * @author fengshuonan + * @date 2020/12/27 17:22 + */ + public static Boolean getCaptchaOpen() { + return ConfigContext.me().getSysConfigValueWithDefault("SYS_CAPTCHA_OPEN", Boolean.class, SystemConstants.DEFAULT_CAPTCHA_OPEN); + } + +}