• SpringBoot Spring Security的基本配置


    Spring Boot针对Spring Security提供了自动化配置方案,因此可以使SpringSecurity非常容易地整合进Spring Boot项目中,这也是在Spring Boot项目中使用Spring Security的优势。

    添加依赖:

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

    默认的用户名是user,默认的登录密码则在每次启动项目时随机生成,查看项目启动日志

    配置用户名和密码:

    可以在application.properties中配置默认的用户名、密码以及用户角色,配置方式如下

    spring:
      security:
        user:
          name: xc
          password: 123456
          roles: admin

    当开发者在application.properties中配置了默认的用户名和密码后,再次启动项目,项目启动日志就不会打印出随机生成的密码了,用户可直接使用配置好的用户名和密码登录

    基于内存的认证:

    开发者也可以自定义类继承自WebSecurityConfigurerAdapter,进而实现对Spring Security更多的自定义配置,例如基于内存的认证,配置方式如下:

    @Configuration
    public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Bean
        PasswordEncoder passwordEncoder() {
            return NoOpPasswordEncoder.getInstance();
        }
    
        // 配置用户
        @Override
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.inMemoryAuthentication()
                    .withUser("root").password("123").roles("ADMIN", "DBA")
                    .and()
                    .withUser("admin").password("123").roles("ADMIN", "USER")
                    .and()
                    .withUser("sang").password("123").roles("USER");
        }
    
        // 配置资源
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests()// 调用authorizeRequests()方法开启HttpSecurity的配置
                    .antMatchers("/admin/**").hasRole("ADMIN")//表示用户访问“/admin/**”模式的URL必须具备ADMIN的角色
                    .antMatchers("/user/**").access("hasAnyRole('ADMIN','USER')")
                    .antMatchers("/db/**").access("hasRole('ADMIN') and hasRole('DBA')")
                    .anyRequest().authenticated()//表示除了前面定义的URL模式之外,用户访问其他的URL都必须认证后访问(登录后访问)
    
                    .and()
                    .formLogin()// 表示开启表单登录
                    .loginPage("/login_page")//这个login_page就是开发者自定义的登录页面,而不再是Spring Security提供的默认登录页。
                    .loginProcessingUrl("/login")//配置了登录接口为“/login”,配置loginProcessingUrl接口主要是方便Ajax或者移动端调用登录接口
                    .usernameParameter("name")//登录参数中用户名默认命名为username
                    .passwordParameter("passwd")//密码默认命名为password
                    .successHandler((req, resp, auth) -> {
                        /*
                         * 定义了登录成功的处理逻辑。用户登录成功后可以跳转到某一个页面,也可以返回一段JSON,这个要看具体业务逻辑,
                         * 本案例假设是第二种,用户登录成功后,返回一段登录成功的JSON。
                         * onAuthenticationSuccess方法的第三个参数Authentication一般用来获取当前登录用户的信息,
                         * 在登录成功后,可以获取当前登录用户的信息一起返回给客户端。
                         */
                        resp.setContentType("application/json;charset=utf-8");
                        resp.setStatus(200);
    
                        Map<String, Object> map = new HashMap<>();
                        map.put("status", 200);
                        map.put("msg", auth.getPrincipal());
    
                        PrintWriter out = resp.getWriter();
                        out.write(new ObjectMapper().writeValueAsString(map));
                        out.flush();
                        out.close();
                    })
                    .failureHandler((req, resp, e) -> {
                        /*
                         * 定义了登录失败的处理逻辑,和登录成功类似,不同的是,登录失败的回调方法里有一个AuthenticationException参数,
                         * 通过这个异常参数可以获取登录失败的原因,进而给用户一个明确的提示。
                         */
                        resp.setContentType("application/json;charset=utf-8");
                        resp.setStatus(401);
    
                        Map<String, Object> map = new HashMap<>();
                        map.put("status", 401);
    
                        if (e instanceof LockedException) {
                            map.put("msg", "账户被锁定,登录失败!");
                        } else if (e instanceof BadCredentialsException) {
                            map.put("msg", "账户名或密码输入错误,登录失败!" + e.getMessage());
                        } else if (e instanceof DisabledException) {
                            map.put("msg", "账户被禁用,登录失败!");
                        } else if (e instanceof AccountExpiredException) {
                            map.put("msg", "账户已过期,登录失败!");
                        } else if (e instanceof CredentialsExpiredException) {
                            map.put("msg", "密码已过期,登录失败!");
                        } else {
                            map.put("msg", "登录失败!");
                        }
                        PrintWriter out = resp.getWriter();
                        out.write(new ObjectMapper().writeValueAsString(map));
                        out.flush();
                        out.close();
                    })
                    .permitAll()// 最后还配置了permitAll,表示和登录相关的接口都不需要认证即可访问
    
                    .and()
                    .logout()//表示开启注销登录的配置
                    .logoutUrl("/logout")//表示配置注销登录请求URL为“/logout”,默认也是“/logout”
                    .clearAuthentication(true)//表示是否清除身份认证信息,默认为true,表示清除
                    .invalidateHttpSession(true)//表示是否使Session失效,默认为true
                    .addLogoutHandler((req, resp, auth) -> {
                        /*
                         * 配置一个LogoutHandler,开发者可以在LogoutHandler中完成一些数据清除工作,例如Cookie的清除
                         */
                    })
                    .logoutSuccessHandler((req, resp, auth) -> resp.sendRedirect("/login_page"))// 配置一个LogoutSuccessHandler,开发者可以在这里处理注销成功后的业务逻辑,例如返回一段JSON提示或者跳转到登录页面等
    
                    .and().csrf().disable();//表示关闭csrf
        }
    
    }
    

    多个HttpSecurity:

    如果业务比较复杂,开发者也可以配置多个HttpSecurity,实现对WebSecurityConfigurerAdapter的多次扩展,代码如下

    /**
     * 配置多个HttpSecurity时,MultiHttpSecurityConfig不需要继承WebSecurityConfigurerAdapter,
     * 在MultiHttpSecurityConfig中创建静态内部类继承WebSecurityConfigurerAdapter即可,
     */
    @Configuration
    /*
     * 开发者也可以通过注解来灵活地配置方法安全,要使用相关注解,首先要通过@EnableGlobalMethodSecurity注解开启基于注解的安全配置
     * prePostEnabled=true会解锁@PreAuthorize和@PostAuthorize两个注解,顾名思义,
     * @PreAuthorize注解会在方法执行前进行验证,
     * 而@PostAuthorize注解在方法执行后进行验证。
     * securedEnabled=true会解锁@Secured注解。
     */
    @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
    public class MultiHttpSecurityConfig {
    
        @Bean
        PasswordEncoder passwordEncoder() {
            /*
             * Spring Security提供了多种密码加密方案,官方推荐使用BCryptPasswordEncoder,
             * BCryptPasswordEncoder使用BCrypt强哈希函数,开发者在使用时可以选择提供strength和SecureRandom实例。
             * strength越大,密钥的迭代次数越多,密钥迭代次数为2^strength。strength取值在4~31之间,默认为10。
             */
            return new BCryptPasswordEncoder(10);
        }
    
        @Autowired
        protected void configure(AuthenticationManagerBuilder auth) throws Exception {
            auth.inMemoryAuthentication()
                    .withUser("root")
                    .password("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq")
                    .roles("ADMIN", "DBA")
                    .and()
                    .withUser("admin")
                    .password("$2a$10$RMuFXGQ5AtH4wOvkUqyvuecpqUSeoxZYqilXzbz50dceRsga.WYiq")
                    .roles("ADMIN", "USER")
                    .and()
                    .withUser("sang")
                    .password("$2a$10$eUHbAOMq4bpxTvOVz33LIehLe3fu6NwqC9tdOcxJXEhyZ4simqXTC")
                    .roles("USER");
        }
    
        @Configuration
        @Order(1) // 静态内部类上添加@Configuration注解和@Order注解,@Order注解表示该配置的优先级,数字越小优先级越大,未加@Order注解的配置优先级最小。
        public static class AdminSecurityConfig extends WebSecurityConfigurerAdapter {
            @Override
            protected void configure(HttpSecurity http) throws Exception {
                http.antMatcher("/admin/**").authorizeRequests()
                        .anyRequest().hasRole("ADMIN");
            }
        }
    
        @Configuration
        public static class OtherSecurityConfig extends WebSecurityConfigurerAdapter {
            @Override
            protected void configure(HttpSecurity http) throws Exception {
                http.authorizeRequests()
                        .anyRequest().authenticated()
    
                        .and()
                        .formLogin()
                        .loginProcessingUrl("/login")
                        .usernameParameter("name")//登录参数中用户名默认命名为username
                        .passwordParameter("passwd")//密码默认命名为password
                        .permitAll()
    
                        .and()
                        .csrf()
                        .disable();
            }
        }
    }
    

      

      

    文章参考: Spring Boot+Vue全栈开发实战 - 10.1 Spring Security的基本配置

  • 相关阅读:
    redis要注意的一些知识
    redis数据类型及常用命令使用
    基于zookeeper的分布式锁
    基于redis的分布式锁
    基于数据库的分布式锁
    数据库的4中隔离级别
    远程调用历史及代码编写demo
    数据库的ACID跟事务隔离级别
    JAVA8 十大新特性详解
    java8 :: 用法 (JDK8 双冒号用法)
  • 原文地址:https://www.cnblogs.com/ooo0/p/16393843.html
Copyright © 2020-2023  润新知