上一篇:Spring Security OAuth2.0 认证协议【6】准备 RESTful API:swagger、WireMock
下一篇:https://blog.csdn.net/LawssssCat/article/details/105296640

至此,前面的环境搭建,接口准备结束,进入 Spring Security 正题。
代码下载:https://github.com/LawssssCat/v-security/tree/v2.0

内容简介

  • Spring Security 基本原理
  • 用户名 + 密码认证
  • 手机号 + 短信认证

会以表单登录为起点,逐渐添加概念和扩展场景,最终形成较为复杂的案例。

HTTP Basic 认证

spring security 默认就是 http basic 认证,我们只需要:

重新打开 spring security,并运行程序

只要添加了 spring security 就会默认开启 httpbasic 模式,之前开发 api 关了,现在打开,并运行。

测试

访问: http://localhost:8080/user/1
就到了我们熟悉的 httpBasic 认证了

如果看不到 http basic 认证,
而是 page not found

只需要去到全局处理,把 自定义的 ErrorController 实现类去掉即可
(当时是处理 404 请求,而开启 security 后,404 会到认证界面,且security优先级更低,因此会到 上面界面,而不是security 的 http basic 认证。如果两个都想开,那么调下优先级即可)

表单认证

<mark>提高代码重用性,所以所有跟认证授权相关的代码会写在 v-security-browser 里面,而 v-security-demo 只是使用 browser 的写好安全模块</mark>。

编写安全配置类

<mark>在 v-security-borwser 模块中</mark>
创建 package:cn.vshop.security.browser
创建类 BrowserSecurityConfig

package cn.vshop.security.browser;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

/** * {@link WebSecurityConfigurerAdapter}: * spring security 提供的 {@link WebSecurity} 适配器 * 一个帮我们实现了大部分{@link WebSecurityConfigurer}接口的抽象类 * <p> * 提供了可以重写的configure方法,在方法内可以装配自定义的Filter配置 * 其指定的Filter会被生产为{@link FilterChainProxy} * 最终以{@link DelegatingFilterProxy}作为spring Security Filter Chain起作用 * <p> * 即:其实现是用来配置spring Security Filter Chain的 * * * @author alan smith * @version 1.0 * @date 2020/4/3 12:15 */
@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        // 指定身份认证方式为表单
        http.formLogin()
                .and()
                // 并且认证请求
                .authorizeRequests()
                // 全部请求,都需要认证
                .anyRequest().authenticated();

    }
}

启动并访问

http://localhost:8080/user/1


Spring Security 基本原理

Spring Security 其实就是一堆的过滤器链(如下图绿色部分

其中

  • UsernamePasswordAuthenticationFilter 对应的是表单 登录
  • BasicAuthenticationFilter 对应的则是 HttpBasic 登录

<mark>身份认证</mark> 流程

  • 判断是否登录请求
  • 查看是否携带登录名、密码
    • 如果有用户名密码,就尝试使用 UsernamePasswordAuthenticationFilter 登录
  • 如果没有,就把请求交给下一个过滤器
    • 如果请求头中有 basic 开头的 authentication 的信息,就会交给 BasicAuthenticationFilter 处理

<mark>请求拦截</mark> 流程

在交给 (上图绿色)认证过滤器处理后,最终会来到 FilterSecurityInterceptor *** (如下图橙色
(过滤器、***知识在 第四章 末尾有讲)


FilterSecurityInterceptor 可以理解为最终的守门人,在他身后的,便是我们编写的 REST API 服务了。
能否真正访问到 这些服务,全由 FilterSecurityInterceptor 决定。

<mark>而决定的依据就是我们上面写的代码</mark>

<mark>错误处理</mark> 流程

如果 FilterSecurityInterceptor 判断了不能访问,会根据不同访问的原因抛出响应的异常。
这些异常的处理***是位于 FilterSecurityInterceptor 前面的 ExceptionTranslationFilter如下图蓝色

ExceptionTranslationFilter 处理的依据 1、是根据抛出的异常。2、是根据我们写的认证形式

<mark>而我们要做的 spring Security 开发,就是添加 绿色的过滤器</mark>

源码分析

眼见为实

<mark>有了上面原理,下面我们打断点,跟着源码走一遍</mark>

## 打断点

第一个断点

打在 UserController 的 query 方法上,<mark>代表最终认证成功</mark>

第二断点

FilterSecurityInterceptor示意图中的橙色) 的 invok 方法上打断点
(打在 token 上,代表认证结束)

第三个断点

ExceptionTranslationFilter 上打断点,看出现认证异常后的处理

第四个断点

打在 UsernamePasswordAuthenticationFilter 上,看看如何密码认证的
(我们后面要自定义,即覆盖这里的操作的)

## Debug

程序 debug 运行起来 ,依次访问,观测运行流程

  1. 访问: http://localhost:8080/user
    因为没有携带登录信息,所以直接通过(原理图中)绿色的过滤器,来到了(原理图中)蓝色的异常过滤器,并且准备往下面的***传递


    来到 FilterSecurityInterceptor 进行判断能否访问后面的请求
    (因为没有登录,所以,拿到token 这一步会报错,异常会返回到 上面的 ExceptionTranslationFilter)


    捕获到了异常,然后就是重定向到登录页面


    直接放行,前端就会显示登录页面

  2. 输入用户名密码登录

    会来到 UsernamePasswordAuthenticationFilter 的 attemptAuthentication 方法






    继续往下,就进到我们写的 api 里面了