spring session 是为了session共享 后端是几台集群。
直接上配置:
spring-security.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task.xsd">
<security:http pattern="/packages/index/**" security="none" />
<security:http pattern="/packages/pages/**" security="none" />
<security:http pattern="/packages/sidebarfile.json" security="none" />
<security:http pattern="/favicon.ico" security="none" />
<security:http pattern="/goToLogin.html" security="none" />
<security:http pattern="/index.html" security="none" />
<security:http pattern="/login.json" security="none" />
<security:http pattern="/loginPrompt.html" security="none" />
<security:http pattern="/pseudo_login.html" security="none" />
<security:http pattern="/mvc/dispatch" create-session="always" auto-config='true'>
<security:intercept-url pattern="/mvc/dispatch" access="permitAll" />
<security:csrf disabled="true" />
<security:custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
<security:session-management
session-authentication-strategy-ref="sas" />
</security:http>
<security:authentication-manager>
<security:authentication-provider user-service-ref="jbpUserDetailsService" />
</security:authentication-manager>
<security:global-method-security pre-post-annotations="enabled" />
<bean id="redirectSessionInformationExpiredStrategy"
class="org.springframework.security.web.session.SimpleRedirectSessionInformationExpiredStrategy">
<constructor-arg name="invalidSessionUrl" value="/goLogin.html" />
</bean>
<bean id="concurrencyFilter"
class="org.springframework.security.web.session.ConcurrentSessionFilter">
<constructor-arg name="sessionRegistry" ref="sessionRegistry" />
<constructor-arg name="sessionInformationExpiredStrategy" ref="redirectSessionInformationExpiredStrategy" />
</bean>
<bean id="sas"
class="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy">
<constructor-arg>
<list>
<bean
class="org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy">
<constructor-arg ref="sessionRegistry" />
<property name="maximumSessions" value="1" />
</bean>
<bean
class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy">
</bean>
<bean
class="org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy">
<constructor-arg ref="sessionRegistry" />
</bean>
</list>
</constructor-arg>
</bean>
<bean id="sessionRegistry"
class="org.springframework.session.security.SpringSessionBackedSessionRegistry">
<constructor-arg ref="sessionRepository" />
</bean>
</beans>
<bean class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy"></bean>
有时候会报 SessionFixation的问题 导致登录不上去 就是 session 销毁重建的过程失败 没有创建出新的session 就tomcat集群时会报这个问题 没找到解决方式 。可以注释掉这句
<bean class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy"></bean>
让他不走SessionFixation的方法就行 虽然会导致登陆后 sessionid不变 但是内网的项目无所谓了。
用的security 5.0.0
之前用了废弃的方法 导致重定向 空指针
错误配置如下:
<bean id="concurrencyFilter"
class="org.springframework.security.web.session.ConcurrentSessionFilter">
<constructor-arg name="sessionRegistry" ref="sessionRegistry" />
<constructor-arg value="/goLogin.html" />
</bean>
百度不靠谱 还得上spring-security 官网才行。 上官网一看例子 ok 调试一下源码 立马发现问题
旧配置 这个跳转的直接为null导致 500错误。
新配置直接用的response.sendRedirect(url)进行跳转。
登录代码里还得添加手动session注册
@Autowired
private CompositeSessionAuthenticationStrategy sas;
private void registerTokenIntoSession(User user) throws ServiceException {
Token token = authorizationService.getUserTokenByUserId(user);
List<GrantedAuthority> authorities = authorizationService.getAuthorities(token.getFunc());
Authentication auth = new PreAuthenticatedAuthenticationToken(token.getUser().getAccount(), token.getUser(),
authorities);
auth.setAuthenticated(true);
SecurityContextHolder.getContext().setAuthentication(auth);
long loginTime = System.currentTimeMillis();
HttpSession session = servletRequest.getSession();
session.setAttribute("tUser", token.getUser());
session.setAttribute("loginUserCode", token.getUser().getUserCode());
session.setAttribute("token", token);
session.setAttribute("loginTime", loginTime);
session.setAttribute("SPRING_SECURITY_CONTEXT", SecurityContextHolder.getContext());
sas.onAuthentication(auth, servletRequest, servletResponse); //重点
workDTO.put("token", token);
workDTO.put("loginTime", loginTime);
}
顺便贴一下 logout
public void logout() {
HttpSession session = servletRequest.getSession();
session.removeAttribute("tUser");
session.removeAttribute("loginUserCode");
session.removeAttribute("token");
session.removeAttribute("loginTime");
Cookie[] cookies = servletRequest.getCookies();
for(Cookie cookie:cookies){
if("userId".equals(cookie.getName())){
Cookie dCookie=new Cookie(cookie.getName(),null);
dCookie.setValue(null);
dCookie.setMaxAge(0);//删除登录 cookie
dCookie.setPath(servletRequest.getContextPath());
servletResponse.addCookie(dCookie);
}
}
//返回新的logoutToken session标记
CommonHelper.setLogOutToken(servletResponse,servletRequest,session,true,"logout");
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
new SecurityContextLogoutHandler().logout(ActionContext.getContext().getServletRequest(),
ActionContext.getContext().getServletResponse(), auth);
}