• 【SpringBoot】SpringBoot 与安全Spring Security(二十四)


      本章介绍SpringBoot与安全Spring Security的集成

    Spring Security介绍

      Spring Security是针对Spring项目的安全框架,也是Spring Boot底层安全模块默认的技术选型。他可以实现强大的web安全控制。对于安全控制,我们仅需引入spring-boot-starter-security模块,进行少量的配置,即可实现强大的安全管理。

      重点:

        WebSecurityConfigurerAdapter:自定义Security策略

        AuthenticationManagerBuilder:自定义认证策略

        @EnableWebSecurity:开启WebSecurity模式

    与Spring Security的集成

      项目搭建

      1、新建SpringBoot Web项目,且集成Thymeleaf,pom文件如下:

     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <project xmlns="http://maven.apache.org/POM/4.0.0"
     3          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     4          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     5     <modelVersion>4.0.0</modelVersion>
     6 
     7     <groupId>com.test</groupId>
     8     <artifactId>test-springboot-security</artifactId>
     9     <version>1.0-SNAPSHOT</version>
    10 
    11     <parent>
    12         <groupId>org.springframework.boot</groupId>
    13         <artifactId>spring-boot-starter-parent</artifactId>
    14         <version>2.1.8.RELEASE</version>
    15     </parent>
    16 
    17     <properties>
    18 
    19         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    20         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    21         <java.version>1.8</java.version>
    22     </properties>
    23 
    24     <dependencies>
    25 
    26         <dependency>
    27             <groupId>org.springframework.boot</groupId>
    28             <artifactId>spring-boot-starter-web</artifactId>
    29         </dependency>
    30 
    31         <dependency>
    32             <groupId>org.springframework.boot</groupId>
    33             <artifactId>spring-boot-starter-thymeleaf</artifactId>
    34         </dependency>
    35 
    36         <dependency>
    37             <groupId>org.springframework.boot</groupId>
    38             <artifactId>spring-boot-starter-test</artifactId>
    39             <scope>test</scope>
    40         </dependency>
    41 
    42     </dependencies>
    43 
    44 
    45     <!-- SpringBoot打包插件,可以将代码打包成一个可执行的jar包 -->
    46     <build>
    47         <plugins>
    48             <plugin>
    49                 <groupId>org.springframework.boot</groupId>
    50                 <artifactId>spring-boot-maven-plugin</artifactId>
    51             </plugin>
    52         </plugins>
    53     </build>
    54 
    55 
    56 </project>
    pom.xml

        项目目录如下:

          

      2、编辑KungFuController,内容如下,主要是访问一些界面

     1 package com.test.springboot.security.controller;
     2 
     3 import org.springframework.stereotype.Controller;
     4 import org.springframework.web.bind.annotation.GetMapping;
     5 import org.springframework.web.bind.annotation.PathVariable;
     6 
     7 @Controller
     8 public class KungFuController {
     9 
    10     private  final String PREFIX = "pages/";
    11 
    12     /**
    13      * 欢迎页
    14      * @return
    15      */
    16     @GetMapping("/")
    17     public String index(){
    18         return "welcome";
    19     }
    20 
    21     /**
    22      * 登录页
    23      * @return
    24      */
    25     @GetMapping("/userlogin")
    26     public String loginPage(){
    27         return PREFIX + "login";
    28     }
    29 
    30     /**
    31      * level1页面映射
    32      * @param path
    33      * @return
    34      */
    35     @GetMapping("/level1/{path}")
    36     public String level1(@PathVariable("path") String path){
    37         return PREFIX + "level1/" + path;
    38     }
    39 
    40 
    41     /**
    42      * level2页面映射
    43      * @param path
    44      * @return
    45      */
    46     @GetMapping("/level2/{path}")
    47     public String level2(@PathVariable("path") String path){
    48         return PREFIX + "level2/" + path;
    49     }
    50 
    51     /**
    52      * level3页面映射
    53      * @param path
    54      * @return
    55      */
    56     @GetMapping("/level3/{path}")
    57     public String level3(@PathVariable("path") String path){
    58         return PREFIX + "level3/" + path;
    59     }
    60 
    61 }
    KungFuController.java

      3、新建welcome页面

     1 <!DOCTYPE html>
     2 <html xmlns:th="http://www.thymeleaf.org">
     3 <head>
     4 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
     5 <title>Insert title here</title>
     6 </head>
     7 <body>
     8 <h1 align="center">欢迎光临武林秘籍管理系统</h1>
     9 
    10 <hr>
    11 
    12 <div >
    13     <h3>普通武功秘籍</h3>
    14     <ul>
    15         <li><a th:href="@{/level1/1}">罗汉拳</a></li>
    16         <li><a th:href="@{/level1/2}">武当长拳</a></li>
    17         <li><a th:href="@{/level1/3}">全真剑法</a></li>
    18     </ul>
    19 
    20 </div>
    21 
    22 <div >
    23     <h3>高级武功秘籍</h3>
    24     <ul>
    25         <li><a th:href="@{/level2/1}">太极拳</a></li>
    26         <li><a th:href="@{/level2/2}">七伤拳</a></li>
    27         <li><a th:href="@{/level2/3}">梯云纵</a></li>
    28     </ul>
    29 
    30 </div>
    31 
    32 <div >
    33     <h3>绝世武功秘籍</h3>
    34     <ul>
    35         <li><a th:href="@{/level3/1}">葵花宝典</a></li>
    36         <li><a th:href="@{/level3/2}">龟派气功</a></li>
    37         <li><a th:href="@{/level3/3}">独孤九剑</a></li>
    38     </ul>
    39 </div>
    40 </body>
    41 </html>
    welcome.html

      4、测试,启动项目访问地址:http://localhost:8080,效果如下:

        

      引入Spring Security

      1、在项目中添加spring-boot-starter-security依赖

    1 <!-- 引入Spring Security -->
    2 <dependency>
    3     <groupId>org.springframework.boot</groupId>
    4     <artifactId>spring-boot-starter-security</artifactId>
    5 </dependency> 

      2、编辑一个类MySecurityConfig,继承WebSecurityConfigurerAdapter,用来配置Security内容

     1 package com.test.springboot.security.config;
     2 
     3 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
     4 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
     5 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
     6 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
     7 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
     8 
     9 // 开启认证
    10 @EnableWebSecurity
    11 public class MySecurityConfig extends WebSecurityConfigurerAdapter {
    12 
    13     // 定义请求规则
    14     @Override
    15     protected void configure(HttpSecurity http) throws Exception {
    16 //        super.configure(http);
    17         // 定制请求的授权规则
    18         http.authorizeRequests().antMatchers("/").permitAll()
    19                 .antMatchers("/level1/**").hasRole("VIP1")
    20                 .antMatchers("/level2/**").hasRole("VIP2")
    21                 .antMatchers("/level3/**").hasRole("VIP3");
    22 
    23     }
    24 
    25 }

        可以看到,主要是配置类请求的规则,对"/"请求放行,对"/level1/**"请求必须要有"VIP1"角色等

      3、重启项目,http://localhost:8080,效果如下:

        

        测试结果:"/level1/**"请求,权限验证不通过,会报错 Access Denied (拒绝访问)

      登录注销功能

      1、编辑MySecurityConfig类

        通过http.formLogin();开启登录功能

        通过http.logout();开启注销功能

        通过重写configure(AuthenticationManagerBuilder auth)方法,将认证信息存到内存中

     1 @EnableWebSecurity
     2 public class MySecurityConfig extends WebSecurityConfigurerAdapter {
     3 
     4     // 定义请求规则
     5     @Override
     6     protected void configure(HttpSecurity http) throws Exception {
     7 //        super.configure(http);
     8         // 定制请求的授权规则
     9         http.authorizeRequests().antMatchers("/").permitAll()
    10                 .antMatchers("/level1/**").hasRole("VIP1")
    11                 .antMatchers("/level2/**").hasRole("VIP2")
    12                 .antMatchers("/level3/**").hasRole("VIP3");
    13 
    14         // 开启登录功能,效果:如果没有登录,没有权限就会来到登录页面
    15         http.formLogin();
    16         //        .loginPage("/userlogin")
    17         //        .usernameParameter("user").passwordParameter("pwd");
    18 
    19         // 1、/login来到登录页
    20         // 2、重定向到/login?error表示登录失败
    21         // 3、更多详情规定
    22         // 4、默认post形式的login代表登录
    23         // 5、一但定制loginPage,loginPage的post请求就是登录
    24 
    25         // 开启自动配置的注销功能
    26         // logoutSuccessUrl成功注销返回界面
    27         http.logout().logoutSuccessUrl("/");
    28         // 1、访问 /logout 表示用户注销,清空session
    29         // 2、注销成功会返回 /login?logout
    30 
    31         // 开启记住我功能
    32         http.rememberMe();
    33                 //.rememberMeParameter("remember");
    34         // 1、登录成功以后,将cookie发送给浏览器保存,以后访问自动带上cookie,检查通过免登录
    35         // 2、点击注销后会删除cookie
    36 
    37     }
    38 
    39     // 定义认证规则
    40     @Override
    41     protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    42 //        super.configure(auth);
    43 
    44         BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    45 
    46         // 认证信息存储到内存中
    47         auth.inMemoryAuthentication()
    48                 .passwordEncoder(passwordEncoder)
    49                 .withUser("zhangsan").password(passwordEncoder.encode("123456")).roles("VIP1", "VIP2")
    50                 .and()
    51                 .withUser("lisi").password(passwordEncoder.encode("123456")).roles("VIP2", "VIP3")
    52                 .and()
    53                 .withUser("wangwu").password(passwordEncoder.encode("123456")).roles("VIP1", "VIP3");
    54     }
    55

      2、在welconme页面增加注销按钮,内容如下,注销的url地址是:"/logout"

    1 <form th:action="@{/logout}" method="post">
    2     <input type="submit" value="注销"/>
    3 </form>

      3、重新启动项目,测试,效果如下:

        

      整合Thymeleaf 与 Spring Security

        引入spring security之后,要想在thymeleaf中使用权限的相关内容,需要引入新的jar包。

        功能:

          1)判断用户是否有权限:sec:authorize="isAuthenticated()

          2)获取用户名称:sec:authentication="name"

          3)获取角色名称:sec:authentication="principal.authorities"

      1、引入依赖thymeleaf-extras-springsecurity5,此依赖可以在spring-boot-dependencies pom中找到

    1 <!-- 引入Thymeleaf与Security整合的模块,可以在spring-boot-dependencies pom中找到 -->
    2 <dependency>
    3     <groupId>org.thymeleaf.extras</groupId>
    4     <artifactId>thymeleaf-extras-springsecurity5</artifactId>
    5 </dependency>

      2、编辑welcome界面

     1 <!DOCTYPE html>
     2 <html xmlns:th="http://www.thymeleaf.org"
     3       xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
     4 <head>
     5     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
     6     <title>Insert title here</title>
     7 </head>
     8 <body>
     9 <h1 align="center">欢迎光临武林秘籍管理系统</h1>
    10 <div sec:authorize="!isAuthenticated()">
    11     <h2 align="center">游客您好,如果想查看武林秘籍 <a th:href="@{/userlogin}">请登录</a></h2>
    12 </div>
    13 <div align="center" sec:authorize="isAuthenticated()">
    14     <h2><span sec:authentication="name"></span> - 您好,您的角色有:
    15         <span sec:authentication="principal.authorities"></span></h2>
    16     <form th:action="@{/logout}" method="post">
    17         <input type="submit" value="注销"/>
    18     </form>
    19 </div>
    20 
    21 <hr>
    22 
    23 <div sec:authorize="hasRole('VIP1')">
    24     <h3>普通武功秘籍</h3>
    25     <ul>
    26         <li><a th:href="@{/level1/1}">罗汉拳</a></li>
    27         <li><a th:href="@{/level1/2}">武当长拳</a></li>
    28         <li><a th:href="@{/level1/3}">全真剑法</a></li>
    29     </ul>
    30 
    31 </div>
    32 
    33 <div sec:authorize="hasRole('VIP2')">
    34     <h3>高级武功秘籍</h3>
    35     <ul>
    36         <li><a th:href="@{/level2/1}">太极拳</a></li>
    37         <li><a th:href="@{/level2/2}">七伤拳</a></li>
    38         <li><a th:href="@{/level2/3}">梯云纵</a></li>
    39     </ul>
    40 
    41 </div>
    42 
    43 <div sec:authorize="hasRole('VIP3')">
    44     <h3>绝世武功秘籍</h3>
    45     <ul>
    46         <li><a th:href="@{/level3/1}">葵花宝典</a></li>
    47         <li><a th:href="@{/level3/2}">龟派气功</a></li>
    48         <li><a th:href="@{/level3/3}">独孤九剑</a></li>
    49     </ul>
    50 </div>
    51 </body>
    52 </html>

      3、重启项目,测试效果如下:

        

      其他还有其他功能,如自定义登录界面等,参考官网:https://spring.io/projects/spring-security

      本例完整代码如下:

        MySecurityConfig.java

     1 package com.test.springboot.security.config;
     2 
     3 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
     4 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
     5 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
     6 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
     7 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
     8 
     9 // 开启认证
    10 @EnableWebSecurity
    11 public class MySecurityConfig extends WebSecurityConfigurerAdapter {
    12 
    13     // 定义请求规则
    14     @Override
    15     protected void configure(HttpSecurity http) throws Exception {
    16 //        super.configure(http);
    17         // 定制请求的授权规则
    18         http.authorizeRequests().antMatchers("/").permitAll()
    19                 .antMatchers("/level1/**").hasRole("VIP1")
    20                 .antMatchers("/level2/**").hasRole("VIP2")
    21                 .antMatchers("/level3/**").hasRole("VIP3");
    22 
    23         // 开启登录功能,效果:如果没有登录,没有权限就会来到登录页面
    24         http.formLogin()
    25                 .loginPage("/userlogin")
    26                 .usernameParameter("user").passwordParameter("pwd");
    27 
    28         // 1、/login来到登录页
    29         // 2、重定向到/login?error表示登录失败
    30         // 3、更多详情规定
    31         // 4、默认post形式的login代表登录
    32         // 5、一但定制loginPage,loginPage的post请求就是登录
    33 
    34         // 开启自动配置的注销功能
    35         // logoutSuccessUrl成功注销返回界面
    36         http.logout().logoutSuccessUrl("/");
    37         // 1、访问 /logout 表示用户注销,清空session
    38         // 2、注销成功会返回 /login?logout
    39 
    40         // 开启记住我功能
    41         http.rememberMe()
    42                 .rememberMeParameter("remember");
    43         // 1、登录成功以后,将cookie发送给浏览器保存,以后访问自动带上cookie,检查通过免登录
    44         // 2、点击注销后会删除cookie
    45 
    46     }
    47 
    48     // 定义认证规则
    49     @Override
    50     protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    51 //        super.configure(auth);
    52 
    53         BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
    54 
    55         // 认证信息存储到内存中
    56         auth.inMemoryAuthentication()
    57                 .passwordEncoder(passwordEncoder)
    58                 .withUser("zhangsan").password(passwordEncoder.encode("123456")).roles("VIP1", "VIP2")
    59                 .and()
    60                 .withUser("lisi").password(passwordEncoder.encode("123456")).roles("VIP2", "VIP3")
    61                 .and()
    62                 .withUser("wangwu").password(passwordEncoder.encode("123456")).roles("VIP1", "VIP3");
    63     }
    64 }
    MySecurityConfig.java

        welcome.html

     1 <!DOCTYPE html>
     2 <html xmlns:th="http://www.thymeleaf.org"
     3       xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
     4 <head>
     5     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
     6     <title>Insert title here</title>
     7 </head>
     8 <body>
     9 <h1 align="center">欢迎光临武林秘籍管理系统</h1>
    10 <div sec:authorize="!isAuthenticated()">
    11     <h2 align="center">游客您好,如果想查看武林秘籍 <a th:href="@{/userlogin}">请登录</a></h2>
    12 </div>
    13 <div align="center" sec:authorize="isAuthenticated()">
    14     <h2><span sec:authentication="name"></span> - 您好,您的角色有:
    15         <span sec:authentication="principal.authorities"></span></h2>
    16     <form th:action="@{/logout}" method="post">
    17         <input type="submit" value="注销"/>
    18     </form>
    19 </div>
    20 
    21 <hr>
    22 
    23 <div sec:authorize="hasRole('VIP1')">
    24     <h3>普通武功秘籍</h3>
    25     <ul>
    26         <li><a th:href="@{/level1/1}">罗汉拳</a></li>
    27         <li><a th:href="@{/level1/2}">武当长拳</a></li>
    28         <li><a th:href="@{/level1/3}">全真剑法</a></li>
    29     </ul>
    30 
    31 </div>
    32 
    33 <div sec:authorize="hasRole('VIP2')">
    34     <h3>高级武功秘籍</h3>
    35     <ul>
    36         <li><a th:href="@{/level2/1}">太极拳</a></li>
    37         <li><a th:href="@{/level2/2}">七伤拳</a></li>
    38         <li><a th:href="@{/level2/3}">梯云纵</a></li>
    39     </ul>
    40 
    41 </div>
    42 
    43 <div sec:authorize="hasRole('VIP3')">
    44     <h3>绝世武功秘籍</h3>
    45     <ul>
    46         <li><a th:href="@{/level3/1}">葵花宝典</a></li>
    47         <li><a th:href="@{/level3/2}">龟派气功</a></li>
    48         <li><a th:href="@{/level3/3}">独孤九剑</a></li>
    49     </ul>
    50 </div>
    51 </body>
    52 </html>
    welcome.html

        login.html

     1 <!DOCTYPE html>
     2 <html xmlns:th="http://www.thymeleaf.org">
     3 <head>
     4 <meta charset="UTF-8">
     5 <title>Insert title here</title>
     6 </head>
     7 <body>
     8     <h1 align="center">欢迎登陆武林秘籍管理系统</h1>
     9     <hr>
    10     <div align="center">
    11         <form th:action="@{/userlogin}" method="post">
    12             用户名:<input name="user"/><br>
    13             密码:<input name="pwd"><br/>
    14             <input type="checkbox" name="remember"> 记住我<br/>
    15             <input type="submit" value="登陆">
    16         </form>
    17     </div>
    18 </body>
    19 </html>
    login.html
  • 相关阅读:
    vue @click.native和@click.stop和@click.self
    CSS改变图片颜色的filter(滤镜)属性
    iframe自适应内容高度
    python将两个列表对应成为字典
    Scrapy307重定向
    scrapy- invalid hostname: 'http'
    tensorflow2.0常用操作记录
    深度学习之Xavier初始化
    win10上tensorflow-gpu2.0安装完全指南
    如何使用Ubuntu/Linux系统远程连接Windows桌面
  • 原文地址:https://www.cnblogs.com/h--d/p/12507900.html
Copyright © 2020-2023  润新知