From e067c8ea2c0c05726be50f995d8a3b60cacdaae4 Mon Sep 17 00:00:00 2001 From: winLsy <18332763730@163.com> Date: Wed, 17 Jan 2018 22:17:50 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/BrowserSecurityBeanConfig.java | 39 ++++++++ .../browser/config/BrowserSecurityConfig.java | 25 +++-- .../controller/BrowserSecurityController.java | 2 +- .../session/AbstractSessionStrategy.java | 97 +++++++++++++++++++ .../session/MsExpiredSessionStrategy.java | 38 +++++--- .../session/MsInvalidSessionStrategy.java | 30 ++++++ .../boot-starter-security-core/README.md | 2 +- .../core/master/SecurityConstants.java | 5 + .../core/master/SecurityProperties.java | 10 ++ .../core/master/SessionProperties.java | 47 +++++++++ 10 files changed, 274 insertions(+), 21 deletions(-) create mode 100644 boot-starter/boot-starter-security/boot-starter-security-browser/src/main/java/com/micro/fast/security/browser/config/BrowserSecurityBeanConfig.java create mode 100644 boot-starter/boot-starter-security/boot-starter-security-browser/src/main/java/com/micro/fast/security/browser/session/AbstractSessionStrategy.java create mode 100644 boot-starter/boot-starter-security/boot-starter-security-browser/src/main/java/com/micro/fast/security/browser/session/MsInvalidSessionStrategy.java create mode 100644 boot-starter/boot-starter-security/boot-starter-security-core/src/main/java/com/micro/fast/security/core/master/SessionProperties.java diff --git a/boot-starter/boot-starter-security/boot-starter-security-browser/src/main/java/com/micro/fast/security/browser/config/BrowserSecurityBeanConfig.java b/boot-starter/boot-starter-security/boot-starter-security-browser/src/main/java/com/micro/fast/security/browser/config/BrowserSecurityBeanConfig.java new file mode 100644 index 0000000..aa5d40e --- /dev/null +++ b/boot-starter/boot-starter-security/boot-starter-security-browser/src/main/java/com/micro/fast/security/browser/config/BrowserSecurityBeanConfig.java @@ -0,0 +1,39 @@ +/** + * + */ +package com.micro.fast.security.browser.config; + +import com.micro.fast.security.browser.session.MsExpiredSessionStrategy; +import com.micro.fast.security.browser.session.MsInvalidSessionStrategy; +import com.micro.fast.security.core.master.SecurityProperties; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.web.session.InvalidSessionStrategy; +import org.springframework.security.web.session.SessionInformationExpiredStrategy; + + +/** + * + * @author lsy + */ +@Configuration +public class BrowserSecurityBeanConfig { + + @Autowired + private SecurityProperties securityProperties; + + @Bean + @ConditionalOnMissingBean(InvalidSessionStrategy.class) + public InvalidSessionStrategy invalidSessionStrategy(){ + return new MsInvalidSessionStrategy(securityProperties.getSession().getSessionInvalidUrl()); + } + + @Bean + @ConditionalOnMissingBean(SessionInformationExpiredStrategy.class) + public SessionInformationExpiredStrategy sessionInformationExpiredStrategy(){ + return new MsExpiredSessionStrategy(securityProperties.getSession().getSessionInvalidUrl()); + } + +} diff --git a/boot-starter/boot-starter-security/boot-starter-security-browser/src/main/java/com/micro/fast/security/browser/config/BrowserSecurityConfig.java b/boot-starter/boot-starter-security/boot-starter-security-browser/src/main/java/com/micro/fast/security/browser/config/BrowserSecurityConfig.java index dad5370..1c893c1 100644 --- a/boot-starter/boot-starter-security/boot-starter-security-browser/src/main/java/com/micro/fast/security/browser/config/BrowserSecurityConfig.java +++ b/boot-starter/boot-starter-security/boot-starter-security-browser/src/main/java/com/micro/fast/security/browser/config/BrowserSecurityConfig.java @@ -1,6 +1,7 @@ package com.micro.fast.security.browser.config; import com.micro.fast.security.browser.session.MsExpiredSessionStrategy; +import com.micro.fast.security.browser.session.MsInvalidSessionStrategy; import com.micro.fast.security.core.authentication.mobile.SmsCodeAuthenticationSecurityConfig; import com.micro.fast.security.core.master.SecurityConstants; import com.micro.fast.security.core.master.SecurityProperties; @@ -19,9 +20,10 @@ import org.springframework.security.web.authentication.AuthenticationSuccessHand import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl; import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository; +import org.springframework.security.web.session.InvalidSessionStrategy; +import org.springframework.security.web.session.SessionInformationExpiredStrategy; import org.springframework.social.security.SpringSocialConfigurer; -import javax.annotation.Resource; import javax.sql.DataSource; /** @@ -45,6 +47,13 @@ public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter { //todo 待优化,不唯一,应从启动参数中获取 public static final String DRUID = "/druid/*"; + + @Autowired + private InvalidSessionStrategy invalidSessionStrategy; + + @Autowired + private SessionInformationExpiredStrategy sessionInformationExpiredStrategy; + /** * 注入身份认证框架配置参数对象 */ @@ -121,14 +130,14 @@ public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter { .and() // session管理的配置 .sessionManagement() - //定义session过期的时候处理的url - .invalidSessionUrl("/session/invalid") + //session过期处理的类 + .invalidSessionStrategy(invalidSessionStrategy) //session存在的最大数量 - .maximumSessions(1) - //设置session被替换掉时处理逻辑 - .expiredSessionStrategy(new MsExpiredSessionStrategy()) - //设置不允许第二个用户登录,不设置这句话的话,会替换掉上一个登录用户 - .maxSessionsPreventsLogin(true) + .maximumSessions(securityProperties.getSession().getMaximumSessions()) + //设置是否允许第二个用户登录,如果不阻止的话,会替换掉上一个登录用户 + .maxSessionsPreventsLogin(securityProperties.getSession().isMaxSessionPreventsLogin()) + //设置session被替换掉时处理逻辑,是定义session过期的时候处理的url + .expiredSessionStrategy(sessionInformationExpiredStrategy) .and() .and() .authorizeRequests()//下面是权限配置 diff --git a/boot-starter/boot-starter-security/boot-starter-security-browser/src/main/java/com/micro/fast/security/browser/controller/BrowserSecurityController.java b/boot-starter/boot-starter-security/boot-starter-security-browser/src/main/java/com/micro/fast/security/browser/controller/BrowserSecurityController.java index 8f0c2b7..218cca5 100644 --- a/boot-starter/boot-starter-security/boot-starter-security-browser/src/main/java/com/micro/fast/security/browser/controller/BrowserSecurityController.java +++ b/boot-starter/boot-starter-security/boot-starter-security-browser/src/main/java/com/micro/fast/security/browser/controller/BrowserSecurityController.java @@ -7,7 +7,6 @@ import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.HttpRequest; import org.springframework.http.HttpStatus; import org.springframework.security.web.DefaultRedirectStrategy; import org.springframework.security.web.RedirectStrategy; @@ -30,6 +29,7 @@ import java.util.Map; /** * 自定义登录认证处理方式,当触发登录认证的时候跳转到这里 + * @author lsy */ @RestController public class BrowserSecurityController { diff --git a/boot-starter/boot-starter-security/boot-starter-security-browser/src/main/java/com/micro/fast/security/browser/session/AbstractSessionStrategy.java b/boot-starter/boot-starter-security/boot-starter-security-browser/src/main/java/com/micro/fast/security/browser/session/AbstractSessionStrategy.java new file mode 100644 index 0000000..7d7a54e --- /dev/null +++ b/boot-starter/boot-starter-security/boot-starter-security-browser/src/main/java/com/micro/fast/security/browser/session/AbstractSessionStrategy.java @@ -0,0 +1,97 @@ +package com.micro.fast.security.browser.session; + +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import com.micro.fast.security.core.reponse.ServerResponse; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpStatus; +import org.springframework.security.web.DefaultRedirectStrategy; +import org.springframework.security.web.RedirectStrategy; +import org.springframework.security.web.util.UrlUtils; +import org.springframework.util.Assert; + +import com.fasterxml.jackson.databind.ObjectMapper; + +/** + * @author lsy + */ +public class AbstractSessionStrategy { + + private final Logger logger = LoggerFactory.getLogger(getClass()); + /** + * 跳转的url + */ + private String destinationUrl; + /** + * 重定向策略 + */ + private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); + /** + * 跳转前是否创建新的session + */ + private boolean createNewSession = true; + + private ObjectMapper objectMapper = new ObjectMapper(); + + /** + * + * @param invalidSessionUrl + */ + public AbstractSessionStrategy(String invalidSessionUrl) { + Assert.isTrue(UrlUtils.isValidRedirectUrl(invalidSessionUrl), "url must start with '/' or with 'http(s)'"); + this.destinationUrl = invalidSessionUrl; + } + + + protected void onSessionInvalid(HttpServletRequest request, HttpServletResponse response) throws IOException { + + if (createNewSession) { + request.getSession(); + } + + String sourceUrl = request.getRequestURI(); + String targetUrl; + + if (StringUtils.endsWithIgnoreCase(sourceUrl, ".html")) { + targetUrl = destinationUrl+".html"; + logger.info("session失效,跳转到"+targetUrl); + redirectStrategy.sendRedirect(request, response, targetUrl); + }else{ + String message = "session已失效"; + if(isConcurrency()){ + message = message + ",有可能是并发登录导致的"; + } + response.setStatus(HttpStatus.UNAUTHORIZED.value()); + response.setContentType("application/json;charset=UTF-8"); + response.getWriter().write(objectMapper.writeValueAsString(ServerResponse.errorMsg(message))); + } + + } + + /** + * session失效是否是并发导致的 + * @return + */ + protected boolean isConcurrency() { + return false; + } + + /** + * Determines whether a new session should be created before redirecting (to + * avoid possible looping issues where the same session ID is sent with the + * redirected request). Alternatively, ensure that the configured URL does + * not pass through the {@code SessionManagementFilter}. + * + * @param createNewSession + * defaults to {@code true}. + */ + public void setCreateNewSession(boolean createNewSession) { + this.createNewSession = createNewSession; + } + +} diff --git a/boot-starter/boot-starter-security/boot-starter-security-browser/src/main/java/com/micro/fast/security/browser/session/MsExpiredSessionStrategy.java b/boot-starter/boot-starter-security/boot-starter-security-browser/src/main/java/com/micro/fast/security/browser/session/MsExpiredSessionStrategy.java index 53a885a..54219e8 100644 --- a/boot-starter/boot-starter-security/boot-starter-security-browser/src/main/java/com/micro/fast/security/browser/session/MsExpiredSessionStrategy.java +++ b/boot-starter/boot-starter-security/boot-starter-security-browser/src/main/java/com/micro/fast/security/browser/session/MsExpiredSessionStrategy.java @@ -1,19 +1,35 @@ +/** + * + */ package com.micro.fast.security.browser.session; +import java.io.IOException; + +import javax.servlet.ServletException; + import org.springframework.security.web.session.SessionInformationExpiredEvent; import org.springframework.security.web.session.SessionInformationExpiredStrategy; -import javax.servlet.ServletException; -import java.io.IOException; - /** - * 处理session顶替的策略 - * @author lsy + * @author zhailiang + * */ -public class MsExpiredSessionStrategy implements SessionInformationExpiredStrategy { - @Override - public void onExpiredSessionDetected(SessionInformationExpiredEvent sessionInformationExpiredEvent) throws IOException, ServletException { - sessionInformationExpiredEvent.getResponse().setContentType("application/json;charset=UTF-8"); - sessionInformationExpiredEvent.getResponse().getWriter().write("并发登录"); - } +public class MsExpiredSessionStrategy extends AbstractSessionStrategy implements SessionInformationExpiredStrategy { + + public MsExpiredSessionStrategy(String invalidSessionUrl) { + super(invalidSessionUrl); + } + + + @Override + public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException, ServletException { + onSessionInvalid(event.getRequest(), event.getResponse()); + } + + + @Override + protected boolean isConcurrency() { + return true; + } + } diff --git a/boot-starter/boot-starter-security/boot-starter-security-browser/src/main/java/com/micro/fast/security/browser/session/MsInvalidSessionStrategy.java b/boot-starter/boot-starter-security/boot-starter-security-browser/src/main/java/com/micro/fast/security/browser/session/MsInvalidSessionStrategy.java new file mode 100644 index 0000000..df75a9d --- /dev/null +++ b/boot-starter/boot-starter-security/boot-starter-security-browser/src/main/java/com/micro/fast/security/browser/session/MsInvalidSessionStrategy.java @@ -0,0 +1,30 @@ +/** + * + */ +package com.micro.fast.security.browser.session; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.security.web.session.InvalidSessionStrategy; + +/** + * @author zhailiang + * + */ +public class MsInvalidSessionStrategy extends AbstractSessionStrategy implements InvalidSessionStrategy { + + public MsInvalidSessionStrategy(String invalidSessionUrl) { + super(invalidSessionUrl); + } + + @Override + public void onInvalidSessionDetected(HttpServletRequest request, HttpServletResponse response) + throws IOException, ServletException { + onSessionInvalid(request, response); + } + +} diff --git a/boot-starter/boot-starter-security/boot-starter-security-core/README.md b/boot-starter/boot-starter-security/boot-starter-security-core/README.md index 2f143ae..09a206c 100644 --- a/boot-starter/boot-starter-security/boot-starter-security-core/README.md +++ b/boot-starter/boot-starter-security/boot-starter-security-core/README.md @@ -34,7 +34,7 @@ weChat 第三方登录 - `ms.security.social.weChat.appId` 类比qq登录 - `ms.security.social.weChat.appSecret` 类比qq登录 - `ms.security.social.weChat.providerId` 类比qq登录 -绑定,解绑第三方用户 +### 绑定,解绑第三方用户 - 查询已绑定的用户,请求`/connect`接口即可,要求当前登录的用户放入session中的是SocialUser的对象,能获取到getId - 绑定用户就是发起post请求`/connect/providerId`即可.可以使用自定义名称为`qqConnectedView`或`weChatConnectedView`的bean来自定义视图 - 解除绑定的时候,发送delete请求`/connect/providerId`删除社交登录的信息即可。返回的视图和绑定的时候使用相同的视图,在视图里面做逻辑判断 diff --git a/boot-starter/boot-starter-security/boot-starter-security-core/src/main/java/com/micro/fast/security/core/master/SecurityConstants.java b/boot-starter/boot-starter-security/boot-starter-security-core/src/main/java/com/micro/fast/security/core/master/SecurityConstants.java index 17217f9..335d56c 100644 --- a/boot-starter/boot-starter-security/boot-starter-security-core/src/main/java/com/micro/fast/security/core/master/SecurityConstants.java +++ b/boot-starter/boot-starter-security/boot-starter-security-core/src/main/java/com/micro/fast/security/core/master/SecurityConstants.java @@ -36,4 +36,9 @@ public interface SecurityConstants { */ String GET_VALIDATE_CODE_PREFIX = "/code/"; + /** + * session失效的处理地址 + */ + String DEFAULT_SESSION_INVALID_URL = "/ms-session-invalid.html"; + } diff --git a/boot-starter/boot-starter-security/boot-starter-security-core/src/main/java/com/micro/fast/security/core/master/SecurityProperties.java b/boot-starter/boot-starter-security/boot-starter-security-core/src/main/java/com/micro/fast/security/core/master/SecurityProperties.java index 804736c..db009dc 100644 --- a/boot-starter/boot-starter-security/boot-starter-security-core/src/main/java/com/micro/fast/security/core/master/SecurityProperties.java +++ b/boot-starter/boot-starter-security/boot-starter-security-core/src/main/java/com/micro/fast/security/core/master/SecurityProperties.java @@ -28,6 +28,16 @@ public class SecurityProperties { private SocialProperties social = new SocialProperties(); + private SessionProperties session = new SessionProperties(); + + public SessionProperties getSession() { + return session; + } + + public void setSession(SessionProperties session) { + this.session = session; + } + public Boolean getCreateRememberTable() { return createRememberTable; } diff --git a/boot-starter/boot-starter-security/boot-starter-security-core/src/main/java/com/micro/fast/security/core/master/SessionProperties.java b/boot-starter/boot-starter-security/boot-starter-security-core/src/main/java/com/micro/fast/security/core/master/SessionProperties.java new file mode 100644 index 0000000..0bc20ec --- /dev/null +++ b/boot-starter/boot-starter-security/boot-starter-security-core/src/main/java/com/micro/fast/security/core/master/SessionProperties.java @@ -0,0 +1,47 @@ +package com.micro.fast.security.core.master; + +/** + * session处理的配置 + * @author lsy + */ +public class SessionProperties { + /** + * 同一个系统中的最大session数,默认1 + */ + private int maximumSessions = 1; + + /** + * 达到最大session时,是否阻止新的登录请求,默认为false,不阻止,新的登录将老的登录 + * 失效掉 + */ + private boolean maxSessionPreventsLogin = false; + + /** + * session失效的时候跳转的地址 + */ + private String sessionInvalidUrl = SecurityConstants.DEFAULT_SESSION_INVALID_URL; + + public int getMaximumSessions() { + return maximumSessions; + } + + public void setMaximumSessions(int maximumSessions) { + this.maximumSessions = maximumSessions; + } + + public boolean isMaxSessionPreventsLogin() { + return maxSessionPreventsLogin; + } + + public void setMaxSessionPreventsLogin(boolean maxSessionPreventsLogin) { + this.maxSessionPreventsLogin = maxSessionPreventsLogin; + } + + public String getSessionInvalidUrl() { + return sessionInvalidUrl; + } + + public void setSessionInvalidUrl(String sessionInvalidUrl) { + this.sessionInvalidUrl = sessionInvalidUrl; + } +}