优化
This commit is contained in:
+39
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
+17
-8
@@ -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()//下面是权限配置
|
||||
|
||||
+1
-1
@@ -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 {
|
||||
|
||||
+97
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
+27
-11
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+30
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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`删除社交登录的信息即可。返回的视图和绑定的时候使用相同的视图,在视图里面做逻辑判断
|
||||
|
||||
+5
@@ -36,4 +36,9 @@ public interface SecurityConstants {
|
||||
*/
|
||||
String GET_VALIDATE_CODE_PREFIX = "/code/";
|
||||
|
||||
/**
|
||||
* session失效的处理地址
|
||||
*/
|
||||
String DEFAULT_SESSION_INVALID_URL = "/ms-session-invalid.html";
|
||||
|
||||
}
|
||||
|
||||
+10
@@ -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;
|
||||
}
|
||||
|
||||
+47
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user