spring security登录认证授权

spring security登录认证授权

是什么

Spring Security 主要实现了Authentication(认证,解决who are you? ) 和 Access Control(访问控制,也就是what are you allowed to do?,也称为Authorization)。Spring Security在架构上将认证与授权分离,并提供了扩展点

使用-1 快速开始 引入依赖,出现登录页面
xml 复制代码
<!-- 实现对 Spring MVC 的自动化配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 实现对 Spring Security 的自动化配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
自定义登录的用户名密码(练手)

配置类继承适配器 WebSecurityConfigurerAdapter, 重写configure方法,实现UserDetailsService接口,设置用户名,密码

从数据库读取密码

配置类继承适配器 WebSecurityConfigurerAdapter, 重写configure方法,实现UserDetailsService接口,调用UserDetailsService的已有的实现类,或者调用自定义的类,实现了UserDetailsService实现类接口,重写loadUserByUsername方法(数据库查登录的用户名密码)

认证逻辑

认证逻辑:SecurityContextPersistenceFilter Security上下文持久化过滤器拿到登录信息,生成session存储 ->SecurityContextHolderStrategy 策略 ->ThreadLocalSecurityContextHolderStrategy 用的ThreadLocal

AbstractAuthenticationProcessingFilter 的 doFilter方法->attemptAuthentication方法->AuthenticationManager接口的authenticate接口方法

->retrieveUser->getUserDetailsService().loadUserByUsername(获取到自定义的数据库获取用户名密码方法)-->authenticate方法中 调用additionalAuthenticationChecks

检查用户名密码的准确性-->正确的话就走认证成功的逻辑,认证成功后 ->SecurityContextHolder.getContext().setAuthentication设置登录信息到上下文;错误就走认真失败的逻辑

自定义认证成功失败的处理


自定义登录成功失败逻辑(执行方法步骤)原理:

认证成功后: successForwardUrl-->ForwardAuthenticationSuccessHandler->调用了AuthenticationSuccessHandler 的onAuthenticationSuccess 方法

因此可以实现AuthenticationSuccessHandler接口,重写 onAuthenticationSuccess 方法

认证失败同理:failureForwardUrl->ForwardAuthenticationFailureHandler->调用了 ForwardAuthenticationFailureHandler的 onAuthenticationFailure 方法

因此可以实现 ForwardAuthenticationFailureHandler接口,重写 onAuthenticationFailure 方法

会话管理(session)

是什么 ?http请求是无状态的,因此需要在浏览器和服务器端存储状态,即会话。

tomcat 会生成session对象,响应的时候会带给客户端存到浏览器的Cookie中,

下次再请求服务器时,带上JSESSIONID,和服务器的JSESSIONID比对,相同的话响应,否则不响应
原理 :SecurityContextHolder.getContext().getAuthentication()可以获取到登录信息,因为登录的认证信息存在 SecurityContext上下文中

AbstractAuthenticationProcessingFilter 的 doFilter方法 -> successfulAuthentication 认证成功后 ->SecurityContextHolder.getContext().setAuthentication 登录的认证信息存在 SecurityContext上下文中

会话并发控制-spring security实现

同一个账号只能同时登录一次(后面登录人把前面登录人挤掉)--->可以用redis实现,此处是用spring security实现
http.sessionManagement().maximumSessions(1)

原理:AbstractAuthenticationProcessingFilter -> sessionStrategy.onAuthentication()-> ConcurrentSessionControlAuthenticationStrategy 的onAuthentication方法比较当前登录的session个数是否小于我们自己设置 -> 是的话就session 设置过期- >ConcurrentSessionFilter 并发session过滤器 -> doFilter方法 -> 没有过期则登录成功,否则走session过期策略

可自定义实现SessionInformationExpiredStrategy接口重写onExpiredSessionDetected方法

问题:http.sessionManagement().maximumSessions(1).maxSessionsPreventsLogin(true) //超过最大的登录数,阻止登录

问题:我们在yml配置的http session设置的超时时间和内部SessionInformation 是重新的一个session,超时时间和之前不同,导致http session设置的超时时间超时了,但是SessionInformation 没超时会报多人同时登录的错误最好不要用,可以用redis实现

会话并发控制-redis实现

实现原理:引入的spring session包中有个session仓库的过滤器 SessionRepositoryFilter -> doFilter方法 ->commitSession ->sessionRepository.save(session)实现了重写了RedisSessionRepository中save 方法,把session存到redis中

1.引入spring session依赖

xml 复制代码
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.1.0</version>
</dependency>

2.修改application.yml

复制代码
xml
 session:
    store-type: redis
  redis:
    host: localhost
    port: 6379

3.开启多个项目实例即可测试

Remember me实现

设置数据源,Spring Security会自动把用户信息存储到数据源中,下次登录直接比对数据库值就ok

原理:RememberMeAuthenticationFilter -> doFilter方法 -> autoLogin ->AbstractRememberMeServices的autoLogin ->PersistentTokenBasedRememberMeServices 的processAutoLoginCookie 取出remember-me的值拆分为series和token 去数据库根据series找到记录,看token是否一致一致就调用 getUserDetailsService().loadUserByUsername方法,实现自动登录

退出登录

原理:LogoutFilter-> doFilter方法 -> SecurityContextLogoutHandler的logout方法,setAuthentication为null清除认证状态,销毁HTTPSession对象

SimpleUrlLogoutSuccessHandler的onLogoutSuccess 重定向到登录页面

csrf跨站请求伪造

从 Spring Security4开始CSRF防护默认开启,默认会拦截请求,进行CSRF处理。CSRF为了保证不是其他第三方网站访问,要求访问时携带参数名为 _csrf 值为token(token 在服务端产生,在渲染请求页面时埋入页面)的内容,如果token和服务端的token匹配成功,则正常访问。

原理:CsrfFilter -> doFilter方法 -> 如果没有token 先生成一个,然后放到填充到CSRF_TOKEN中返回给页面,会再走一遍doFilter方法去比对CSRF_TOKEN和服务端的token是否能匹配成功,成功则可以访问,否则不能访问


授权

这里是引用访问控制url的匹配

antMatchers ant 表达式,统配符 ? 匹配任何单字符,* 匹配0或者任意数量的字符, ** 匹配0或者更多的目录

hasAuthority 有...的角色权限

hasAnyAuthority 有多个角色权限,符合一个即可

自定义403处理方案

使用 Spring Security 时经常会看见 403(无权限)。Spring Security 支持自定义权限受限处理,需要

实现 AccessDeniedHandler接口

基于方法的授权

1.JSR250注解,可以定义在方法和类上面

配置类开启@EnableGlobalMethodSecurity(jsr250Enabled = true,securedEnabled = true,prePostEnabled = true)

@RolesAllowed 访问对应方法时所应该具有的角色

@PermitAll 不进行权限控制

@DenyAll 无论什么角色都不能访问

2.@Secured注解专门用于判断是否具有角色的,能写在方法或类上。参数要以 ROLE_开头

配置类开启@EnableGlobalMethodSecurity(jsr250Enabled = true,securedEnabled = true,prePostEnabled = true)

3.支持表达式注解

配置类开启@EnableGlobalMethodSecurity(jsr250Enabled = true,securedEnabled = true,prePostEnabled = true)

使用@PreAuthorize和@PostAuthorize 在方法之前,之后进行访问控制





授权原理:FilterSecurityInterceptor -> doFilter方法 -> invoke-> beforeInvocation -> attemptAuthorization -> decide(AffirmativeBased) -> vote 投票是否通过授权通过则可以访问资源,失败则跳转到登录页面认证

相关推荐
BBB努力学习程序设计2 分钟前
Java注解(Annotation)深度解析:从元编程到框架设计
java
2501_916766548 分钟前
【SpringMVC】实现文件上传
java·spring
Jack_abu8 分钟前
详解java中的BlockingQueue阻塞队列
java·juc·阻塞队列·blockingqueue
她说..8 分钟前
Spring AOP场景4——事务管理(源码分析)
java·数据库·spring boot·后端·sql·spring·springboot
爬山算法28 分钟前
Netty(17)Netty如何处理大量的并发连接?
java·后端
spencer_tseng39 分钟前
springcloud + javaframework + h5
java·spring·spring cloud
月明长歌1 小时前
【码道初阶】【Leetcode606】二叉树转字符串:前序遍历 + 括号精简规则,一次递归搞定
java·数据结构·算法·leetcode·二叉树
原来是好奇心1 小时前
深入Spring Boot源码(八):高级特性与扩展点深度解析
java·源码·springboot
oioihoii1 小时前
C++共享内存小白入门指南
java·c++·算法