Spring Security 源码分析八:Spring Security 过滤链二 - Demo 例子

栏目: 后端 · 发布时间: 5年前

内容简介:本文是对 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 登录

Spring Security 源码分析八:Spring Security 过滤链二 - Demo 例子

走 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


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

菜鸟侦探挑战数据分析

菜鸟侦探挑战数据分析

[日] 石田基广 / 支鹏浩 / 人民邮电出版社 / 2017-1 / 42

本书以小说的形式展开,讲述了主人公俵太从大学文科专业毕业后进入征信所,从零开始学习数据分析的故事。书中以主人公就职的征信所所在的商业街为舞台,选取贴近生活的案例,将平均值、t检验、卡方检验、相关、回归分析、文本挖掘以及时间序列分析等数据分析的基础知识融入到了生动有趣的侦探故事中,讲解由浅入深、寓教于乐,没有深奥的理论和晦涩的术语,同时提供了大量实际数据,使用免费自由软件RStudio引领读者进一步......一起来看看 《菜鸟侦探挑战数据分析》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

SHA 加密
SHA 加密

SHA 加密工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具