内容简介:本文是对 Spring Security Core 4.0.4 Release 进行源码分析的系列文章之一;本文为作者的原创作品,转载需注明出处;本章,笔者将试图通过一个 Spring Security 的 Demo 来简单描述一下 Spring Security 过滤链是如何工作的;该例子中将会分别创建两个SecurityFilterChain,一个是
本文是对 Spring Security Core 4.0.4 Release 进行源码分析的系列文章之一;
本文为作者的原创作品,转载需注明出处;
简介
本章,笔者将试图通过一个 Spring Security 的 Demo 来简单描述一下 Spring Security 过滤链是如何工作的;该例子中将会分别创建两个SecurityFilterChain,一个是 /web/** ,一个是 /rest/** 的过滤链;
Demo
该 Demo 是基于 Spring Boot Web Security 所构建而来;根据当前项目需要,版本稍低 1.3.8.RELEASE;
POM
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.shangyang.spring</groupId> <artifactId>security-demo</artifactId> <version>0.0.1-SNAPSHOT</version> <!-- Inherit defaults from Spring Boot --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.3.8.RELEASE</version> </parent> <!-- Add typical dependencies for a web application --> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> </dependencies> <properties> <java.version>1.8</java.version> </properties> <!-- Package as an executable jar --> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
DemoApplication
@Controller @EnableAutoConfiguration public class DemoApplication { ... @Configuration @EnableWebSecurity @Order(1) static class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { auth .inMemoryAuthentication() .withUser("user").password("password").roles("USER").and() .withUser("manager").password("password").roles("MANAGER"); } @Override protected void configure(HttpSecurity http) throws Exception { http.antMatcher("/web/**") // the filter chain defined for web request .authorizeRequests() .antMatchers("/web/report/**").hasRole("MANAGER") .anyRequest().authenticated() .and() .formLogin() // login 的相对路径必须与 security chain 的的相对路径吻合,这里是 /web/**;注意 login 分两步,一步是 Getter 会到 login.html,另外一步是从 login.html -> post -> /web/login/ .loginPage("/web/login") // 允许访问 .permitAll(); } } @Configuration @EnableWebSecurity @Order(2) static class RestSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.antMatcher("/rest/**") // the filter chain defined for web request; .csrf().disable() // rest 请求无需 CSRF Token; .authorizeRequests() .antMatchers("/rest/hello").hasRole("USER") .anyRequest().authenticated() .and() .httpBasic(); } } public static void main(String[] args) throws Exception { SpringApplication.run(DemoApplication.class, args); } }
通过 WebSecurityConfigurerAdapter 配置实现了两个 Spring Security 过滤链,一个是 /web/** ,一个是 /rest/** 的过滤链;从名称上可以清晰的看到,一个过滤链是用来处理 web request ,另外一个过滤链用来处理 restful request ;
-
web request 过滤链
使用 Form Login 的方式进行登录验证;
用户需要由 MANAGER 角色才能访问相关资源;
使用 CSRF token filter 进行验证;
……
-
restful request 过滤链
使用 Basic Auth 的方式进行登录验证;
用户需要由 USER 角色才能访问相关资源;
不使用 CSRF token filter 进行验证;
……
Web 登录
走 login form 的流程,针对该流程,Spring Security 会提供基于 URL /web/login/ 的 post 请求的方法,用来验证用户基于表单的认证请求;
login.html
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" class="uk-height-1-1"> <head> <meta charset="UTF-8"/> <title>OAuth2 SSO Demo</title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/uikit/2.26.3/css/uikit.gradient.min.css"/> </head> <body class="uk-height-1-1"> <div class="uk-vertical-align uk-text-center uk-height-1-1"> <div class="uk-vertical-align-middle" style="width: 250px;"> <h1>Login Form</h1> <p class="uk-text-danger" th:if="${param.error}"> Login failed ... </p> <p class="uk-text-success" th:if="${param.logout}"> Logout succeeded. </p> <form class="uk-panel uk-panel-box uk-form" method="post" th:action="@{/web/login}"> <div class="uk-form-row"> <input class="uk-width-1-1 uk-form-large" type="text" placeholder="Username" name="username" value="user"/> </div> <div class="uk-form-row"> <input class="uk-width-1-1 uk-form-large" type="password" placeholder="Password" name="password" value="password"/> </div> <div class="uk-form-row"> <button class="uk-width-1-1 uk-button uk-button-primary uk-button-large">Login</button> </div> </form> </div> </div> </body> </html>
注意
,这里 form 表单的提交必须使用链接 /web/login ;
<form class="uk-panel uk-panel-box uk-form" method="post" th:action="@{/web/login}">
如果,将表单的提交链接错误的写成了 /login ,
<form class="uk-panel uk-panel-box uk-form" method="post" th:action="@{/login}">
如果是这样设置的话,用户登录以后将会报错,报错提示根据相关链接 /login 找不到对应的 Controller;根本原因是, /login 访问链接不能命中 /web/** 安全链,而 login form 既处理表单的部分是通过该安全链中的一个 Filter 既是 LoginFilter
来处理的,而该 Filter 的拦截链接在初始化的时候,其拦截地址,既是 loginUrl 必须匹配 /web/** 的规则,所以,初始化后, loginUrl 的初始值为 /web/login ;
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- Vue源码阅读--过滤器
- Spring Security系列之核心过滤器源码分析(四)
- 网关 Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.3) 之 RouteToRequestUrlFilter
- 网关 Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.8) 之 WebClientHttpRoutingFilter
- 网关 Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.5) 之 ForwardRoutingFilter
- 网关 Spring-Cloud-Gateway 源码解析 —— 过滤器 (4.6) 之 WebSocketRoutingFilter
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
编程珠玑(英文版・第2版)
[美] Jon Bentley / 人民邮电出版社 / 2010-8 / 39.00元
多年以来,当程序员们推选出最心爱的计算机图书时,《编程珠玑》总是位列前列。正如自然界里珍珠出自细沙对牡蛎的磨砺,计算机科学大师Jon Bentley以其独有的洞察力和创造力,从磨砺程序员的实际问题中凝结出一篇篇不朽的编程“珠玑”。这些文章是《ACM通讯》最受欢迎的专栏文章,最终结集为两部书出版。本书为第一卷,主要讨论计算机科学中最本质的问题:如何正确选择和高效地实现算法。 在书中,作者选取许......一起来看看 《编程珠玑(英文版・第2版)》 这本书的介绍吧!