SpringSecurity + OAuth2 详解
SpringSecurity入门到精通
- **********************************************************
- **************** SpringSecurity 介绍 ****************
- **********************************************************
- 一、入门
- 1.简介与选择
- 2.入门案例-默认的登录和登出接口
- 3.登录经过了哪些步骤
- 二、基础的自定义认证
- 1.自定义UserDetailsService - 实现用户信息获取
- 2.替换默认密码处理PasswordEncoder - 实现密码比对
- 3.自定义登录接口 - 替换默认登录接口
- 4.放行登录接口配置
- 5.登录失败自定义异常处理
- 6.增加拦截器/过滤器验证登录状态
- 7.登出接口与Token续签
- 三、自定义授权
- 1.UserDetails增加存储权限信息并通过getAuthorities返回
- 2.UserDetailsService中封装权限和角色到UserDetails
- 3.使用PreAuthorize验证权限
- 4.自定义授权异常响应
- 四、其他关键信息
- 1.自定义权限认证方法
- 2.一些钩子函数
- **********************************************************
- ******************** OAuth2.0 介绍 *******************
- **********************************************************
- 一、OAuth2.0 介绍
- 1.授权码模式
- 2.简化模式
- 3.密码模式
- 4.客户端模式
- 5.自带接口介绍
- 二、Springcloud集成OAuth2:授权
- 1.引入依赖
- 2.提供Springsecurity配置
- 2.1 自定义UserDetailsService的实现类,获取用户信息和权限信息
- 2.2 自定义UserDetails实现类,用以封装UserDetailsService的信息返回
- 2.3 配置SpringSecurity的配置类WebSecurityConfigurerAdapter
- 3.配置OAuth:AuthorizationServerConfigAdapter
- 4.验证授权码模式
- 5.验证简化模式
- 6.验证密码模式
- 7.验证客户端模式
- 8.验证原生接口-令牌有效性:/oauth/check_token
- 三、Springcloud集成OAuth2:资源
- 2.编写配置类
- 3.添加一个测试接口
- 4.总结
**********************************************************
**************** SpringSecurity 介绍 ****************
**********************************************************
一、入门
SpringSecurity当下最主流的两种认证授权框架之一,另一个则是Shiro。在2021之前shiro的使用还是比较多的,但随着SpringBoot越来越流行,SpringSecurity也越来越流行,主要还是因为SpringSecurity的配置越来越简洁了,不会像之前那样复杂。而shiro是Apache下的认证授权框架,典型特点事轻量易上手,使用起来也比较简洁。SpringSecurity则是相对来说重一些,不过同时可支持自定义的配置也会多一些,所以他的可扩展性要高于Shiro,随着Spring生态的发展,SpringSecurity则越来越受欢迎了,这篇文章用以总结SpringSecurity的常用功能
1.简介与选择
安装框架的核心功能都是认证与授权,无论是哪种安全框架,均是如此,SpringSecurity自然也是如此。
认证:验证当前用户是否是系统的合法用户
授权:对合法用户进行权限授予,用户携带授权信息方可正常访问系统资源或接口
目前Spring生态内对于集成SpringSecurity更友好,所以越来越多得项目均是选择SpringSecurity作为认证授权的框架,其实说是SpringSecurity是相较于Shiro难一些,不过都很简单,只需要花个半天到一天的时间就可以学会使用。
2.入门案例-默认的登录和登出接口
这一节先展示下SpringSecurity的Demo,了解下SpringSecurity默认提供的登录和登出功能。
-
1.导入依赖
这里使用的是父工程进行管理的项目,
SpringBoot版本是2.6.11
SpringCloud版本是2021.0.4
SpringCloud- Alibaba 版本是2021.0.4.0
org.springframework.boot spring-boot-starter-security org.springframework.boot spring-boot-starter-web org.projectlombok lombok
-
2.直接启动工程后访问他的登录接口
无需提供任何配置,导入依赖后可以直接启动工程,下面是默认的登录和登出接口
默认登录接口:http://localhost:port/login
-
3 登录系统
这里使用默认用户user,密码在项目启动时动态生成的,每次重启都会重新生成一个,位置如下,此时我们可以写一个web接口进行验证, 如果不登录是无法访问到web接口的,若是完成登录这可以正常访问web接口。
登录后会跳转一个白页,当然这样的登录控制是不可能满足我们需要的,首先我们需要的用户信息是需要从数据库获取,然后密码存储在数据库肯定是密文,那么需要更换密码比对等。
3.登录经过了哪些步骤
在这个前端发起登录请求时会经过过滤器链的处理,其中以下标出的可以先做认识下:
- UsernamePasswordAuthenticationFilter : 验证用户密码,进行授权
- DefaultLoginPageGeneratingFilter 提供默认登录页
- DefaultLogoutPageGeneratingFilter 提供默认登出页
- FilterSecurityInterceptor 授权
这几个过滤器需要着重说下的是UsernamePasswordAuthenticationFilter,这个过滤器是在我们不使用自定义登录时SpringSecurity提供的用于认证和授权的一个过滤器(自定义以后系统会自动剔除),下面先简单说下他的处理过程,方便第二部分理解为什么要替换这些类或者接口的实现。
1-UsernamePasswordAuthenticationFilter.attemptAuthentication
尝试开始进行认证,该方法获取用户名密码形成token,然后调用
2-AuthenticationManager.authenticate(实际执行ProviderManager.authenticate)
这里仍然不是最终验证的地方,会继续向下调用
3-AuthenticationProvider.authenticate(实际执行DaoAuthenticationProvider.authenticate)
这个方法的内部先是获取UserDetails的对象这里通过 retrieveUser -> UserDetailsService.loadUserByUsername,默认场景下返回的是User(UserDetails的实现类),这个user则是从内存中去获取的信息
这个方法的内部再通过additionalAuthenticationChecks方法传入token,user等验证密码是否正确
所有认证完成后返回一个Authentication对象给到调用者。
这样便完成了一次简单的认证了,这也是入门案例的执行流程。
二、基础的自定义认证
通过上面的一部分的第3节可以大概知道了认证的流程,那么下面我们做bean的替换时就会比较清晰的知道为什么要替换了
1.自定义UserDetailsService - 实现用户信息获取
上面介绍了UserDetailsService的作用是为了获取到一个UserDetails,如果我们不做更改系统返回的是User,这个User是SpringSecurity提供的一个UserDetails的实现类,那如果我们想要从数据库获取用户信息,就至少需要做两个事情。
①从新实现UserDetailsService的loadUserByUsername方法,从数据库抓取用户和密码
②自定义一个UserDetails,以满足真实的需要
根据上面的分析,我们先建立一个UserDetails的实现类,供使用,在这之前先建立一个用户的信息的类
// 这是基础的用户信息的POJO @Data @Accessors(chain = true) public class UserDTO { private String username; private String password; }
然后我们就可以实现自己的UserDetails了,如下
package com.cheng.ebbingauthservice.security.bean; import com.cheng.ebbingauthservice.dto.UserDTO; import lombok.Data; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import java.util.Collection; /** * @author pcc * @version 1.0.0 * @description SpringSecurity通过这个类获取到用户信息 */ @Data public class UserDetailItem implements UserDetails { private UserDTO userDTO; @Override public Collection
-