• SpringBoot整合SpringSecurity


    SpringBoot整合SpringSecurity

    1. 认识SpringSecurity

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

    记住几个类:

    • WebSecurityConfigurerAdapter:自定义Security策略
    • AuthenticationManagerBuilder:自定义认证策略
    • @EnableWebSecurity:开启WebSecurity模式

    Spring Security的两个主要目标是 “认证” 和 “授权”(访问控制)。

    “认证”(Authentication)

    身份验证是关于验证您的凭据,如用户名/用户ID和密码,以验证您的身份。

    身份验证通常通过用户名和密码完成,有时与身份验证因素结合使用。

    “授权” (Authorization)

    授权发生在系统成功验证您的身份后,最终会授予您访问资源(如信息,文件,数据库,资金,位置,几乎任何内容)的完全权限。

    这个概念是通用的,而不是只在Spring Security 中存在。

    2. 认证和授权

    目前,我们的测试环境,是谁都可以访问的,我们使用 Spring Security 增加上认证和授权的功能

    1、引入 Spring Security 模块

    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    

    2、编写 Spring Security 配置类

    参考官网:https://spring.io/projects/spring-security

    查看我们自己项目中的版本,找到对应的帮助文档:

    https://docs.spring.io/spring-security/site/docs/5.3.2.RELEASE/reference/html5 #servlet-applications 8.16.4

    @EnableWebSecurity
    public class Config extends WebSecurityConfigurerAdapter {
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http
                .apply(customDsl())
                    .flag(true)
                    .and()
                ...;
        }
    }
    
    @EnableWebSecurity // 开启WebSecurity模式
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
       @Override
       protected void configure(HttpSecurity http) throws Exception {
           
      }
    }
    

    3、定制请求的授权规则

    @Override
    protected void configure(HttpSecurity http) throws Exception {
       // 定制请求的授权规则
       // 首页所有人可以访问
       http.authorizeRequests().antMatchers("/").permitAll()
      .antMatchers("/vip1/**").hasRole("vip1")
      .antMatchers("/vip2/**").hasRole("vip2")
      .antMatchers("/vip3/**").hasRole("vip3");
    }
    

    4、测试一下:发现除了首页都进不去了!因为我们目前没有登录的角色,因为请求需要登录的角色拥有对应的权限才可以!

    5、在configure()方法中加入以下配置,开启自动配置的登录功能!

    // 开启自动配置的登录功能
    // /login 请求来到登录页
    // /login?error 重定向到这里表示登录失败
    http.formLogin();
    

    6、测试一下:发现,没有权限的时候,会跳转到登录的页面!

    7、查看刚才登录页的注释信息;

    我们可以定义认证规则,重写configure(AuthenticationManagerBuilder auth)方法

    //定义认证规则
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
       
       //在内存中定义,正常因该再数据库取....
       auth.inMemoryAuthentication()
              .withUser("MapleLeaf").password("123456").roles("vip2","vip3")
              .and()
              .withUser("root").password("123456").roles("vip1","vip2","vip3")
              .and()
              .withUser("guest").password("123456").roles("vip1","vip2");
    }
    

    8、测试,我们可以使用这些账号登录进行测试!发现会报错!

    There is no PasswordEncoder mapped for the id “null”

    9、原因,我们要将前端传过来的密码进行某种方式加密,否则就无法登录,修改代码

    //定义认证规则
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
       //Spring security 5.0中新增了多种加密方式,也改变了密码的格式。
       //要想我们的项目还能够正常登陆,需要修改一下configure中的代码。我们要将前端传过来的密码进行某种方式加密
       //spring security 官方推荐的是使用bcrypt加密方式。
       
       auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
              .withUser("maple").password(newBCryptPasswordEncoder().encode("123456")).roles("vip2","vip3")
              .and()
              .withUser("root").password(newBCryptPasswordEncoder().encode("123456")).roles("vip1","vip2","vip3")
              .and()
              .withUser("guest").password(newBCryptPasswordEncoder().encode("123456")).roles("vip1","vip2");
    }
    

    10、测试,发现,登录成功,并且每个角色只能访问自己认证下的规则!搞定

    3、权限控制和注销

    1、开启自动配置的注销的功能

    //定制请求的授权规则
    @Override
    protected void configure(HttpSecurity http) throws Exception {
       //....
       //开启自动配置的注销的功能
       // /logout 注销请求
       //http.logout() //注销后默认跳转到登录页
       // .logoutSuccessUrl("/"); 注销成功来到首页
    	http.logout().logoutSuccessUrl("/");
    }
    

    2、我们可以去测试一下,登录成功后点击注销(/logout),发现注销完毕会跳转到首页!

    4、记住我

    现在的情况,我们只要登录之后,关闭浏览器,再登录,就会让我们重新登录,但是很多网站的情况,就是有一个记住密码的功能,这个该如何实现呢?很简单

    1、开启记住我功能

    //定制请求的授权规则
    @Override
    protected void configure(HttpSecurity http) throws Exception {
    //。。。。。。。。。。。
       //记住我
       http.rememberMe();
    }
    

    2、我们再次启动项目测试一下,发现登录页多了一个记住我功能,我们登录之后关闭 浏览器,然后重新打开浏览器访问,发现用户依旧存在!

    5、定制登录页

    现在这个登录页面都是spring security 默认的,怎么样可以使用我们自己写的Login界面呢?

    1、在刚才的登录页配置后面指定 loginpage

    http.formLogin().loginPage("/login");
    

    2、然后前端也需要指向我们自己定义的 login请求

    <a class="item" href="login">
       <i class="address card icon"></i> 登录
    </a>
    

    注意login.html 请求提交的方式必须为post:

    3、请求提交上来,我们还需要验证处理,怎么做呢?我们可以查看formLogin()方法的源码!我们配置接收登录的用户名和密码的参数!

    http.formLogin()
      .usernameParameter("username")
      .passwordParameter("palssword")
      .loginPage("/login")
      .loginProcessingUrl("/login"); // 登陆表单提交请求
    

    4、在登录页增加记住我的多选框

    <input type="checkbox" name="remember"> 记住我
    

    5、后端验证处理!

    //定制记住我的参数!
    http.rememberMe().rememberMeParameter("remember");
    

    6、测试,OK

    6、完整配置代码

    @EnableWebSecurity
    public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
       //定制请求的授权规则
       @Override
       protected void configure(HttpSecurity http) throws Exception {
    
           http.authorizeRequests().antMatchers("/").permitAll()
          .antMatchers("/vip1/**").hasRole("vip1")
          .antMatchers("/vip2/**").hasRole("vip2")
          .antMatchers("/vip3/**").hasRole("vip3");
    
    
           //开启自动配置的登录功能:如果没有权限,就会跳转到登录页面!
               // /login 请求来到登录页
               // /login?error 重定向到这里表示登录失败
           http.formLogin()
              .usernameParameter("username")
              .passwordParameter("password")
              .loginPage("/login")
              .loginProcessingUrl("/login"); // 登陆表单提交请求
    
           //开启自动配置的注销的功能
               // /logout 注销请求
               // .logoutSuccessUrl("/"); 注销成功来到首页
    
           http.csrf().disable();//关闭csrf功能:跨站请求伪造,默认只能通过post方式提交logout请求
           http.logout().logoutSuccessUrl("/");
    
           //记住我
           http.rememberMe().rememberMeParameter("remember");
      }
    
       //定义认证规则
       @Override
       protected void configure(AuthenticationManagerBuilder auth) throws Exception {
           //在内存中定义,也可以在jdbc中去拿....
           //Spring security 5.0中新增了多种加密方式,也改变了密码的格式。
           //要想我们的项目还能够正常登陆,需要修改一下configure中的代码。我们要将前端传过来的密码进行某种方式加密
           //spring security 官方推荐的是使用bcrypt加密方式。
    
           auth.inMemoryAuthentication().passwordEncoder(newBCryptPasswordEncoder())
                  .withUser("maple").password(newBCryptPasswordEncoder().encode("123456")).roles("vip2","vip3")
                  .and()
                  .withUser("root").password(newBCryptPasswordEncoder().encode("123456")).roles("vip1","vip2","vip3")
                  .and()
                  .withUser("guest").password(newBCryptPasswordEncoder().encode("123456")).roles("vip1","vip2");
      }
    }
    
  • 相关阅读:
    冷门Javascript API——element.insertAdjacentHTML
    一些CKEditor定制问题
    HTML中的base标签
    深入Require.js
    狂神说SpringMVC笔记
    GeoServer之Dispatcher类(Controller控制器)
    java之ThreadLocal<>线程
    java获取当前路径&文件读写
    GeoServer服务扩展
    Spring之getBeanNamesForType
  • 原文地址:https://www.cnblogs.com/junlinsky/p/13262413.html
Copyright © 2020-2023  润新知