Session失效时间:

springboot配置session失效时间,只需要在application.properties里配置

#session超时时间,低于60秒按60秒
server.session.timeout = 60

如果想自己定义session失效的提示信息,需要配置:

@Configuration //这是一个配置
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter{
//版本二:可配置的登录页
@Override
protected void configure(HttpSecurity http) throws Exception {
//~~~-------------> 图片验证码过滤器 <------------------
ValidateCodeFilter validateCodeFilter = new ValidateCodeFilter();
//验证码过滤器中使用自己的错误处理
validateCodeFilter.setAuthenticationFailureHandler(imoocAuthenticationFailureHandler);
//配置的验证码过滤url
validateCodeFilter.setSecurityProperties(securityProperties);
validateCodeFilter.afterPropertiesSet(); //~~~-------------> 短信验证码过滤器 <------------------
SmsCodeFilter smsCodeFilter = new SmsCodeFilter();
//验证码过滤器中使用自己的错误处理
smsCodeFilter.setAuthenticationFailureHandler(imoocAuthenticationFailureHandler);
//配置的验证码过滤url
smsCodeFilter.setSecurityProperties(securityProperties);
smsCodeFilter.afterPropertiesSet(); //实现需要认证的接口跳转表单登录,安全=认证+授权
//http.httpBasic() //这个就是默认的弹框认证
//
http
.addFilterBefore(smsCodeFilter, UsernamePasswordAuthenticationFilter.class)
// .apply(imoocSocialSecurityConfig)//社交登录
// .and()
//把验证码过滤器加载登录过滤器前边
.addFilterBefore(validateCodeFilter, UsernamePasswordAuthenticationFilter.class)
//----------表单认证相关配置---------------
.formLogin()
.loginPage(SecurityConstants.DEFAULT_UNAUTHENTICATION_URL) //处理用户认证BrowserSecurityController
//登录过滤器UsernamePasswordAuthenticationFilter默认登录的url是"/login",在这能改
.loginProcessingUrl(SecurityConstants.DEFAULT_LOGIN_PROCESSING_URL_FORM)
.successHandler(imoocAuthenticationSuccessHandler)//自定义的认证后处理器
.failureHandler(imoocAuthenticationFailureHandler) //登录失败后的处理
.and()
//------------记住我相关配置 -------------
.rememberMe()
.tokenRepository(persistentTokenRepository())//TokenRepository,登录成功后往数据库存token的
.tokenValiditySeconds(securityProperties.getBrowser().getRememberMeSeconds())//记住我秒数
.userDetailsService(userDetailsService) //记住我成功后,调用userDetailsService查询用户信息
.and()//-----------session相关配置---------------
.sessionManagement()
// .invalidSessionStrategy(invalidSessionStrategy)
// .maximumSessions(securityProperties.getBrowser().getSession().getMaximumSessions())
.invalidSessionUrl(SecurityConstants.SESSION_INVALID_PAGE) //session失效跳转地址,如果简单的处理只要这一个就够了
// .maximumSessions(1) //一个用户只能登录一次,踢出前边登录用户
// .maxSessionsPreventsLogin(securityProperties.getBrowser().getSession().isMaxSessionsPreventsLogin())//阻止在登录
// .expiredSessionStrategy(sessionInformationExpiredStrategy) //session失效策略
.and() //?俩and为啥呢
// .and()
//-----------授权相关的配置 ---------------------
.authorizeRequests()
// /authentication/require:处理登录,securityProperties.getBrowser().getLoginPage():用户配置的登录页
.antMatchers(SecurityConstants.DEFAULT_UNAUTHENTICATION_URL,
securityProperties.getBrowser().getLoginPage(),//放过登录页不过滤,否则报错
SecurityConstants.DEFAULT_LOGIN_PROCESSING_URL_MOBILE,
SecurityConstants.SESSION_INVALID_PAGE,
SecurityConstants.DEFAULT_VALIDATE_CODE_URL_PREFIX+"/*").permitAll() //验证码
.anyRequest() //任何请求
.authenticated() //都需要身份认证
.and()
.csrf().disable() //关闭csrf防护
.apply(smsCodeAuthenticationSecurityConfig);//把短信验证码配置应用上
}
}

public static final String SESSION_INVALID_PAGE = "/session/invalid";

@GetMapping("/session/invalid")
@ResponseStatus(code = HttpStatus.UNAUTHORIZED)
public SimpleResponse toSessionInvalidPage(){
String message = "session 失效!";
return new SimpleResponse(message);
}

一个账户同时默认是可以在多处登录的,如果想要后边的登录踢出前边的登录,只要放开  .maximumSessions(1) 这句配置即可。

session并发控制:  

也可以自定义session失效策略,自定义一个类ImoocExpiredSessionStrategy2:

package com.imooc.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; /**
* session失效策略,简单版本
* ClassName: ImoocExpiredSessionStrategy
* @Description: TODO
* @author lihaoyang
* @date 2018年3月8日
*/
public class ImoocExpiredSessionStrategy2 implements SessionInformationExpiredStrategy{ /**
* SessionInformationExpiredEvent:session失效事件,能拿到request、response
*/
@Override
public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException, ServletException {
//可以从event中拿到request中的信息
event.getResponse().setContentType("application/json;charset=UTF-8");
event.getResponse().getWriter().write("并发登录!");
} }

加上配置:

.sessionManagement()
// .invalidSessionStrategy(invalidSessionStrategy)
// .maximumSessions(securityProperties.getBrowser().getSession().getMaximumSessions()) .invalidSessionUrl(SecurityConstants.SESSION_INVALID_PAGE) //session失效跳转地址,如果简单的处理只要这一个就够了
.maximumSessions(1) //一个用户只能登录一次,踢出前边登录用户
.expiredSessionStrategy(new ImoocExpiredSessionStrategy2()) //简洁版session失效策略

此时如果第二次登录,第一个登录就会提示:

如果想阻止多处登录,可以加上这句配置:

.sessionManagement()
// .invalidSessionStrategy(invalidSessionStrategy)
// .maximumSessions(securityProperties.getBrowser().getSession().getMaximumSessions()) .invalidSessionUrl(SecurityConstants.SESSION_INVALID_PAGE) //session失效跳转地址,如果简单的处理只要这一个就够了
.maximumSessions(1) //一个用户只能登录一次,踢出前边登录用户
.expiredSessionStrategy(new ImoocExpiredSessionStrategy2()) //简洁版session失效策略
.maxSessionsPreventsLogin(true) //阻止并发登录

此时如果多出登录,后者就会提示

重构:将session失效策略自己实现

/**
*
*/
package com.imooc.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 ImoocInvalidSessionStrategy extends AbstractSessionStrategy implements InvalidSessionStrategy { public ImoocInvalidSessionStrategy(String invalidSessionUrl) {
super(invalidSessionUrl);
} @Override
public void onInvalidSessionDetected(HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
onSessionInvalid(request, response);
} }

session过期策略:

package com.imooc.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; /**
* session失效策略
* ClassName: ImoocExpiredSessionStrategy
* @Description: TODO
* @author lihaoyang
* @date 2018年3月8日
*/
public class ImoocExpiredSessionStrategy extends AbstractSessionStrategy implements SessionInformationExpiredStrategy
{ /**
* SessionInformationExpiredEvent:session失效事件,能拿到request、response
*/
// @Override
// public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException, ServletException {
// event.getResponse().setContentType("application/json;charset=UTF-8");
// event.getResponse().getWriter().write("并发登录!");
// } public ImoocExpiredSessionStrategy(String invalidSessionUrl) {
super(invalidSessionUrl);
} /* (non-Javadoc)
* @see org.springframework.security.web.session.SessionInformationExpiredStrategy#onExpiredSessionDetected(org.springframework.security.web.session.SessionInformationExpiredEvent)
*/
@Override
public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException, ServletException {
onSessionInvalid(event.getRequest(), event.getResponse());
} /* (non-Javadoc)
* @see com.imooc.security.browser.session.AbstractSessionStrategy#isConcurrency()
*/
@Override
protected boolean isConcurrency() {
return true;
} }

AbstractSessionStrategy:

/**
*
*/
package com.imooc.security.browser.session; import java.io.IOException; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; 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;
import com.imooc.security.browser.support.SimpleResponse; /**
* @author zhailiang
*
*/
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
* @param invalidSessionHtmlUrl
*/
public AbstractSessionStrategy(String invalidSessionUrl) {
Assert.isTrue(UrlUtils.isValidRedirectUrl(invalidSessionUrl), "url must start with '/' or with 'http(s)'");
this.destinationUrl = invalidSessionUrl;
} /*
* (non-Javadoc)
*
* @see org.springframework.security.web.session.InvalidSessionStrategy#
* onInvalidSessionDetected(javax.servlet.http.HttpServletRequest,
* javax.servlet.http.HttpServletResponse)
*/
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(new SimpleResponse(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;
} }

配置:

.sessionManagement()
//++++++=基本这样配置++++++++
// .invalidSessionUrl(SecurityConstants.SESSION_INVALID_PAGE) //session失效跳转地址,如果简单的处理只要这一个就够了
// .maximumSessions(1) //一个用户只能登录一次,踢出前边登录用户
// .expiredSessionStrategy(new ImoocExpiredSessionStrategy2()) //简洁版session失效策略
// .maxSessionsPreventsLogin(true) //阻止并发登录 //
//++++++++重构后+++++++
.invalidSessionStrategy(invalidSessionStrategy)
.maximumSessions(securityProperties.getBrowser().getSession().getMaximumSessions())
.maxSessionsPreventsLogin(securityProperties.getBrowser().getSession().isMaxSessionsPreventsLogin())//阻止在登录
.expiredSessionStrategy(sessionInformationExpiredStrategy) //session失效策略

而且变量都做成了可配置的,具体的代码放在了github:

https://github.com/lhy1234/spring-security

Spring Security构建Rest服务-1100-单机Session管理的更多相关文章

  1. Spring Security构建Rest服务-1300-Spring Security OAuth开发APP认证框架之JWT实现单点登录

    基于JWT实现SSO 在淘宝( https://www.taobao.com )上点击登录,已经跳到了 https://login.taobao.com,这是又一个服务器.只要在淘宝登录了,就能直接访 ...

  2. Spring Security构建Rest服务-1202-Spring Security OAuth开发APP认证框架之重构3种登录方式

    SpringSecurityOAuth核心源码解析 蓝色表示接口,绿色表示类 1,TokenEndpoint 整个入口点,相当于一个controller,不同的授权模式获取token的地址都是 /oa ...

  3. Spring Security构建Rest服务-1200-SpringSecurity OAuth开发APP认证框架

    基于服务器Session的认证方式: 前边说的用户名密码登录.短信登录.第三方登录,都是普通的登录,是基于服务器Session保存用户信息的登录方式.登录信息都是存在服务器的session(服务器的一 ...

  4. Spring Security构建Rest服务-1001-spring social开发第三方登录之spring social基本原理

    OAuth协议是一个授权协议,目的是让用户在不将服务提供商的用户名密码交给第三方应用的条件下,让第三方应用可以有权限访问用户存在服务提供商上的资源. 接着上一篇说的,在第三方应用获取到用户资源后,如果 ...

  5. Spring Security构建Rest服务-0900-rememberMe记住我

    Spring security记住我基本原理: 登录的时候,请求发送给过滤器UsernamePasswordAuthenticationFilter,当该过滤器认证成功后,会调用RememberMeS ...

  6. Spring Security构建Rest服务-1201-Spring Security OAuth开发APP认证框架之实现服务提供商

    实现服务提供商,就是要实现认证服务器.资源服务器. 现在做的都是app的东西,所以在app项目写代码  认证服务器: 新建 ImoocAuthenticationServerConfig 类,@Ena ...

  7. Spring Security构建Rest服务-0702-短信验证码登录

    先来看下 Spring Security密码登录大概流程,模拟这个流程,开发短信登录流程 1,密码登录请求发送给过滤器 UsernamePasswordAuthenticationFilter 2,过 ...

  8. Spring Security构建Rest服务-0800-Spring Security图片验证码

    验证码逻辑 以前在项目中也做过验证码,生成验证码的代码网上有很多,也有一些第三方的jar包也可以生成漂亮的验证码.验证码逻辑很简单,就是在登录页放一个image标签,src指向一个controller ...

  9. Spring Security构建Rest服务-0702-个性化用户认证流程2

    登录成功后的处理AuthenticationSuccessHandler: 认证成功后,默认情况下spring security会继续访问之前访问的url,如果想自定义处理逻辑,用默认的就不行了.此时 ...

随机推荐

  1. 解决Jedis链接报超时异常和connection reset异常的方法

    一.链接池配置 <bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig" ...

  2. jedis 链接池使用(转)

    Jedis作为redis的最佳客户端,它提供了连接池的特性,“连接池”在通常情况下可以有效的提高应用的通信能力,并且这是一种良好的设计模式.Jedis的连接池设计基于apache commons-po ...

  3. C和指针小结(C/C++程序设计)

    C和指针 相关基础知识:内存的分配(谭浩强版) 1.整型变量的地址与浮点型/字符型变量的地址区别?(整型变量/浮点型变量的区别是什么) 2.int *p,指向整型数据的指针变量. 3.通过指针变量访问 ...

  4. DatePickerDialog TimePickerDialog

    MainActivity.java        public class MainActivity extends Activity   {       @Override       public ...

  5. Robotframework + Appium 之常用元素定位方法

    任何自动化测试,其实手动测试也是一样的,元素定位(目标定位)是首要任务,这是最直接的测试对象呀! 好了,废话不多说,又到了元素定位啦,之前我们已经介绍过selenium及appium常用的定位方法,下 ...

  6. 微软儿童编程技术,kodu(酷豆)为儿童创造一个游戏世界

    受微软青年星火项目组的邀请,我和微软项目组的朋友参加了一场针对儿童编程的技术指导. 儿童和编程,本来是两个完全不靠边的词.在大家的常规思维中,编程一直是软件开发人员的事情,是高科技类型的工作,高不可攀 ...

  7. 一步一步学习Swift之(二):好玩的工具playground与swfit基础语法

    playground好于在于能一边写代码一边看到输出的常量变量的值.不需要运行模拟器. 我们来试一下该工具的用法. 打开xcode6开发工具,选择Get started with a playgrou ...

  8. c# 1-2+3-4.....求和

    找规律: 下界:1 上界:n class Program { static void Main(string[] args) { ; ; i <=; i++) { ==) { sum -= i; ...

  9. Javassist简介

    Javassist是一个开源的分析.编辑和创建Java字节码的类库.是由东京工业大学的数学和计算机科学系的 Shigeru Chiba (千叶 滋)所创建的.它已加入了开放源代码JBoss 应用服务器 ...

  10. Pacemaker 介绍

    1. 简介 Pacemaker是一个集群资源管理者.他用资源级别的监测和恢复来保证集群服务(aka.资源)的最大可用性.它可以用你所擅长的基础组件(Corosync或者是Heartbeat)来实现通信 ...