学习基于记录,而不止于记录。
希望自己能坚持下去~
0.写在前面
继续上一篇,本篇记录在spring security中对session进行安全管理和配置
spring boot版本:2.2.7.RELEASE
开发工具:IntelliJ IDEA 2018.3.2 (Ultimate Edition)
jdk: java version "1.8.0_181"
maven: 3.3.9
1.session创建策略
- always:如果当前请求没有session存在, Spring Security创建一个session。
- never: Spring Security将永远不会主动创建session,但是如果session已经存在,它将使用该session
- ifRequired (默认) : Spring Security在需要时才创建session.
- stateless: Spring Security不会创建或使用任何session。适合于接口型的无状态应用,该方式节省资源。经常应用于前后端分离的开发中。
2.配置
SecurityConfig.java
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();
http.formLogin()
.loginPage("/login.html")
.usernameParameter("username")
.passwordParameter("password")
.loginProcessingUrl("/login")
.failureHandler(myAuthenticationFailureHandler)
.successHandler(myAuthenticationSuccessHandler)
.and()
.authorizeRequests()
.antMatchers("/login.html", "/login").permitAll()
.antMatchers("/pageA.html", "pageB.html")
.hasAnyAuthority("ROLE_user", "ROLE_admin")
.antMatchers("/syslog.html", "/sysuser.html")
.hasAnyAuthority("ROLE_admin")
.anyRequest().authenticated()
.and()
//session管理,配置创建策略
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
}
3.session会话超时配置
3.1 application.properties
1)server.servlet.session.timeout=15m
,spring boot提供的方式
注意:
最少1分钟,少于1分钟按照1分钟计算。
2)spring.session.timeout = 15m
,继承了spring session内库时的配置
3.2 SecurityConfig.java
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.invalidSessionUrl("/login.html");
可以测试一下,登录后一分钟不做操作,然后在主页点击页面跳转会自动导航向登录页,因为session会话超时了。
4.session保护
- 默认情况下,
migrationSession
保护方式。即对于同一个cookies的SESSIONID用户,每次登录验证将创建一个新的HTTP会话,旧的HTTP会话将无效,并且旧会话的属性将被复制。 - 设置为
none
时,原始会话不会无效 - 设置
newSession
后,将创建一个干净的会话,而不会复制旧会话中的任可属性 - 设置
changeSessionId
后,将修改sessionid将会被修改
配置:
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.invalidSessionUrl("/login.html")
.sessionFixation()
.migrateSession();
这样每次登录session都会重新创建,F12页面控制台查看cookie里面存放的JSESSIONID每次都不一样。
5.cookie安全配置
- httpOnly:如果为true, 则浏览器脚本将无法访问cookie
- secure: 如果为true,则仅通过HTTPS连接发送cookie, HTTP无法携带cookie。
application.properties
server.servlet.session.cookie.http-only=true
server.servlet.session.cookie.secure=false
6.限制最大登录人数和下线
实现SessionInformationExpiredStrategy
接口.
MyExpiredSessionStrategy.java
package com.grj.securityDemo.config;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.grj.securityDemo.model.MyResponse;
import org.springframework.security.web.session.SessionInformationExpiredEvent;
import org.springframework.security.web.session.SessionInformationExpiredStrategy;
import org.springframework.stereotype.Component;
import javax.servlet.ServletException;
import java.io.IOException;
/**
* @Author: grj
* @Date: 2020/6/3 21:33
*/
@Component
public class MyExpiredSessionStrategy implements SessionInformationExpiredStrategy {
private static ObjectMapper objectMapper = new ObjectMapper();
@Override
public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException, ServletException {
event.getResponse().setContentType("application/json;charset=UTF-8");
event.getResponse().getWriter().write(objectMapper.writeValueAsString(MyResponse.getSessionExpiredInstance()));
}
}
SecurityConfig.java
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.invalidSessionUrl("/login.html")
.sessionFixation()
.migrateSession()
//最大登陆人数为1
.maximumSessions(1)
//设置false允许多点登录但是,如果超出最大人数之前的登录会被踢掉
.maxSessionsPreventsLogin(false)
.expiredSessionStrategy(myExpiredSessionStrategy);
MyResponse.java 返回实体的新的工厂方法,其实你直接map或者json存放数据返回也行。
public static MyResponse getSessionExpiredInstance() {
return MyResponse.builder()
.code(500)
.type(ResponseTypeEnum.ERROR)
.data(null)
.message("存在重复登录,当前登录状态被迫下线!")
.build();
}
测试:
在两个浏览器先后登录,之前登录的如果点击任意一个主页链接则会弹窗json数据提示,如下:
image.png
7 总结
至此基本准备操作都已完成,后续将加入动态权限控制,也就是从数据库读取数据对用户进行校验和鉴权。