• springboot security 安全


    spring security几个概念

    “认证”(Authentication) 是建立一个他声明的主体的过程(一个“主体”一般是指用户,设备或一些可以在你的应用程序中执行动作的其他系统) 。
    “授权”(Authorization)指确定一个主体是否允许在你的应用程序执行一个动作的过程。为了抵达需要授权的店,主体的身份已经有认证过程建立。
    这个概念是通用的, 而不仅仅在Spring Security中 , 在Shiro中也是一样的.

     

    Spring Security的 Web&安全几个关键点

    1. 登陆/注销
       HttpSecurity配置登陆、注销功能
    2. Thymeleaf提供的SpringSecurity标签支持
       需要引入thymeleaf-extras-springsecurity4
       sec:authentication=“name” 获得当前用户的用户名
      sec:authorize=“hasRole(‘ADMIN’)” 当前用户必须拥有ADMIN权限时才会显示标签内容
    3. remember me
       表单添加remember-me的checkbox
      配置启用remember-me功能
    4. CSRF(Cross-site request forgery)跨站请求伪造
       HttpSecurity启用csrf功能,会为表单添加_csrf的值,提交携带来预防CSRF; 

     

    我们仅需引入spring-boot-starter-security模块,进行少量的配置,即可实现强大的安全管理。


    security中几个重要的类如下:

    WebSecurityConfigurerAdapter:自定义Security策略
    AuthenticationManagerBuilder:自定义认证策略
    @EnableWebSecurity:开启WebSecurity模式 (在@Controller注解的类上追加)

     

    SpringSecurity在SpringBoot中使用

    springsecurity在什么都不配的情况下,默认帐号是user, 密码在启动日志中随机生成uuid,如下形式

    2019-06-04 09:44:52.852  INFO 33512 --- [           main] b.a.s.AuthenticationManagerConfiguration : 
    Using
    default security password: bc4c813c-b8f9-4cdb-9ca9-b406d3492da9

    pom.xml添加依赖

            <!--在thymeleaf中使用认证标签需要的额外依赖-->
            <dependency>
                <groupId>org.thymeleaf.extras</groupId>
                <artifactId>thymeleaf-extras-springsecurity4</artifactId>
                <version>3.0.2.RELEASE</version>
            </dependency>

    配置MySecurityConfig.java

    官方说明自定义SecurityConfig替换默认配置参考链接: https://docs.spring.io/spring-security/site/docs/5.2.0.BUILD-SNAPSHOT/reference/htmlsingle/#oauth2resourceserver-sansboot

    protected void configure(HttpSecurity http) {
        http
            .authorizeRequests()
                .anyRequest()
           .authenticated()
                .and()
               .oauth2ResourceServer()
                .jwt();
    }

    自定义MySecurityConfig.java

    @EnableWebSecurity //该注解本身就包含@Configuration
    public class MySecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            //super.configure(http);
            //定制授权规则
            http.authorizeRequests().antMatchers("/").permitAll().
                    antMatchers("/level1/**").hasRole("VIP1").
                    antMatchers("/level2/**").hasRole("VIP2").
                    antMatchers("/level3/**").hasRole("VIP3");
        }
    
    }

    配置自动生成的登录页

    开启自动配置的 /login 登录页面,如果不配置, 那么无授权时会报403 Access is denied错误,且页面也不知道跳哪,因为还没有开启自动配置的login登录页面
    ,默认使用的是/login 和 /login?error, 现在改成/userlogin,会经过KungfuController的 @GetMapping("/userlogin")注解的方法.

    也可以配置登录页及登录时的帐号密码字段是什么等.

    http.formLogin().loginPage("/login").usernameParameter("username").passwordParameter("password");

    配置登出界面

    开启自动配置的注销功能,默认访问/logout表示注销,会清空session及cookie,注销成功后返回/login?logout页面

    http.logout().logoutSuccessUrl("/");//自定义注销成功后跳转到/页面

    配置认证规则

    /**
     * 定义认证规则,管理帐号/密码
     *
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //auth.jdbcAuthentication(); //一般用jdbc
    
        //学习用内存认证
        auth.inMemoryAuthentication()
                .withUser("bobo").password("123456").roles("VIP1")
                .and().withUser("sisi").password("123456").roles("VIP1", "VIP2")
                .and().withUser("xixi").password("123456").roles("VIP1", "VIP2", "VIP3");
    }

    在pom.xml中引入thymeleaf依赖的springSecurity标签的插件

    <!--在thymeleaf中使用认证标签需要的额外依赖-->
    <dependency>
        <groupId>org.thymeleaf.extras</groupId>
        <artifactId>thymeleaf-extras-springsecurity4</artifactId>
        <version>3.0.2.RELEASE</version>
    </dependency>

    html标签体中引入security规范

    <html xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">

     

    thymeleaf中显示用户信息

    <div sec:authorize="isAuthenticated()">
        <h2> 您好 , <span sec:authentication="name"></span> 您的角色是 <span sec:authentication="principal.authorities"></span>
        </h2>
    </div>

    thymeleaf中显示判断是否有权限

    <div sec:authorize="hasRole('VIP1')">
            <h3>普通武功秘籍</h3>
            <ul>
                <li><a th:href="@{/level1/1}">罗汉拳</a></li>
                <li><a th:href="@{/level1/2}">武当长拳</a></li>
                <li><a th:href="@{/level1/3}">全真剑法</a></li>
            </ul>
        </div>

    开启记住我功能

     开启记住我功能登录成功,会从服务器返回添加名为remember-me的cookie指令, 以后访问页面都会带上该cookie, 只要服务器通过检查就可以免登录了,默认14天后失效

    http.rememberMe().rememberMeParameter("remember-me");

    此时使用/logout会一并清除名为remember-me的cookie , 因为/logout请求在header头中携带了Max-Age=0参数

     

    自定义登录页,使用/userlogin

            //默认使用的是/login 和 /login?error, 现在改成/userlogin,会经过KungfuController的 @GetMapping("/userlogin")注解的方法
            http.formLogin().loginPage("/userlogin");//.usernameParameter("username").passwordParameter("password");

    默认get形式的/login来到登录页, post形式的/login用来表单登录.

    当自定义了登录页面/userlogin后,那么get形式的/userlogin来到登录页, post形式的/userlogin用来表单登录. 见源码注释说明如下:

     

    最终项目结构

    核心配置类MySecurityConfig.java内容

    package com.example.security.config;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
    
    @EnableWebSecurity //该注解本身就包含@Configuration
    public class MySecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            //super.configure(http);
    
            //定制授权规则
            http.authorizeRequests().antMatchers("/").permitAll().
                    antMatchers("/level1/**").hasRole("VIP1").
                    antMatchers("/level2/**").hasRole("VIP2").
                    antMatchers("/level3/**").hasRole("VIP3");
    
            //参见 HttpSecurity 类的    public FormLoginConfigurer<HttpSecurity> formLogin() 方法注解
            //开启自动配置的 /login 登录页面,如果不配置, 那么无授权时会报403 Access is denied错误,且页面也不知道跳哪,因为还没有开启自动配置的login登录页面
            //默认使用的是/login 和 /login?error, 现在改成/userlogin,会经过KungfuController的 @GetMapping("/userlogin")注解的方法
            http.formLogin().loginPage("/userlogin");//.usernameParameter("username").passwordParameter("password");
    
            //开启自动配置的注销功能,默认访问/logout表示注销,会清空session及cookie,注销成功后返回/login?logout页面
            http.logout().logoutSuccessUrl("/");//自定义注销成功后跳转到/页面
    
            //开启记住我功能登录成功,会从服务器返回添加名为remember-me的cookie指令, 以后访问页面都会带上该cookie, 只要服务器通过检查就可以免登录了,默认14天后失效
            http.rememberMe().rememberMeParameter("remember-me");
        }
    
        /**
         * 定义认证规则,管理帐号/密码
         *
         * @param auth
         * @throws Exception
         */
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            //auth.jdbcAuthentication(); //一般用jdbc
    
            //学习用内存认证
            auth.inMemoryAuthentication()
                    .withUser("bobo").password("123456").roles("VIP1")
                    .and().withUser("sisi").password("123456").roles("VIP1", "VIP2")
                    .and().withUser("xixi").password("123456").roles("VIP1", "VIP2", "VIP3");
        }
    
    
    }

    直接关闭所有Security的所有拦截功能

    http.headers().frameOptions().disable().and().authorizeRequests().antMatchers("/**", "/login*").permitAll(); // 所有用户都可以访问
    http.csrf().disable().authorizeRequests().anyRequest().permitAll().and().logout().permitAll(); //禁用security的 csrf功能

    SpringSecurity默认是禁止接收POST请求的,而GET是默认可以的,官网给出两个解决方案:1是发送请求时带上CSRF的token,2是不推荐的做法(把SpringSecurity的CSRF功能关掉),不然很有可能是get请求正常, 但post请求报403 forbidden

    springboot security版本差异

    帐号密码配置差异(亲测)

    在security 4版本中(springboot1.5中使用), application.yml中简易帐号密码配置如下,没有spring:

    security:
      user:
        name: bobo
        password: 123456

    而在security 5版本中(springboot2开始使用), application.yml中帐号密码配置如下, 多了一层spring: 

    spring:
      security:
        user:
          name: bobo
          password: 123456

    禁用security

    pom.xml中如果存在以下依赖

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

    启动时控制台会随机生成登录密码, 打印如下:

    Using generated security password: 17718027-34f3-444c-9623-7243038d0af9

    请求接口时会跳到登录页 Please sign in

     禁用spring security两种方法, 配置类或启动类上加上如下(二选一)

    @EnableAutoConfiguration(exclude = {SecurityAutoConfiguration.class}) 或者   @SpringBootApplication(exclude = {SecurityAutoConfiguration.class })

    登录问题

    Spring Security在登录验证中增加额外数据(如验证码)==>https://www.cnblogs.com/phoenix-smile/p/5666686.html

    spring security前台登录如何传递多个参数要后台验证==>https://bbs.csdn.net/topics/390493958    (在username里用_分割啊哈哈哈)

    $$$$$$$$$$spring security controller层实现登陆==>https://blog.csdn.net/qq_34675369/article/details/91499798

    我的项目git地址

    https://gitee.com/KingBoBo/springboot-05-security

     最好的教程

    在SpringBoot 中使用Security安全框架==>https://blog.csdn.net/qwe86314/article/details/89509765

     

    相关系列 文章

    SpringBoot 整合 oauth2(三)实现 token 认证==>https://www.jianshu.com/p/19059060036b

    SpringBoot 整合 Security(一)实现用户认证并判断返回json还是view==>https://www.jianshu.com/p/18875c2995f1

    SpringBoot 整合 Security(二)实现验证码登录==>https://www.jianshu.com/p/9d08c767b33e

  • 相关阅读:
    初学JAVA随记——代码练习(输出半个菱形 for语句嵌套)
    初学JAVA随记——代码练习(体重问题,含switch、if else、三元条件运算符)
    初学JAVA随记——代码练习(二元一次方程)
    初学JAVA——语句的几个要点
    初学JAVA随记——运算符的几个要点2
    初学JAVA——试写if条件代码(自身体重为例)
    初学JAVA——运算符的几个要点
    初学JAVA——栈空间堆空间的理解
    自制刻度尺插件-前端简易实现"腾讯信用"界面
    JavaScript快速查找节点
  • 原文地址:https://www.cnblogs.com/whatlonelytear/p/10894040.html
Copyright © 2020-2023  润新知