SpringBoot 安全管理(一)

SpringBoot 安全管理(一)

一、springSecurity入门

  • 添加依赖

    <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    
  • 不做配置时,每次访问都需要验证,用户名默认为user,密码为启动时控制台打印的密文(每次启动都会随机生成),访问/logout即可注销登录

    • 如 Using generated security password: 31612171-4f6a-4c43-92ae-6826bc1d5e49
    • 注意,登录如果404,是因为没有配置页面,登录成功后默认跳转到 “/ ” 下面,没有页面,便404了
  • 手动配置(数据是写死的)

    • 在spring5以后,security是不允许明文的,必须加密

    • 在application.properties中配置

      spring.security.user.name=user
      spring.security.user.password=123
      spring.security.user.roles=admin
      
      
    • 在类中配置(注意继承了WebSecurityConfigurerAdapter,加上Configuration注解)

      @Configuration
      public class SecurityConfig extends WebSecurityConfigurerAdapter {
      
          @Bean
          PasswordEncoder passwordEncoder(){
              //这个已过期,作用是无需加密,允许明文
              return NoOpPasswordEncoder.getInstance();
          }
      
          @Override
          protected void configure(AuthenticationManagerBuilder auth) throws Exception {
              auth.inMemoryAuthentication()
                      .withUser("user").password("123").roles("admin")
                      .and()	//可重复添加
                      .withUser("user1").password("123").roles("super");
          }
      }
      
  • HttpSecurity(登陆注销相关的配置,有点长,请耐心观看)

     @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests() //开启登录配置
                    .antMatchers("admin/**").hasRole("admin") // 访问/admin下需要admin角色
                    .antMatchers("user/**").hasAnyRole("admin","user")  //访问/user下需要admin或user其中一个角色
                    .anyRequest().authenticated() //除以上2个url 访问其他只需要登录
                    .and()
                    .formLogin()
                    .loginProcessingUrl("/login")   //配置登录接口
            		.usernameParameter("uname") //定义用户名的key
                    .passwordParameter("passwd") //定义密码的key
                    //.successForwardUrl("xxxxx") 定义登录成功后跳转的页面(前后端不分离)
              
                    .successHandler(new AuthenticationSuccessHandler() {
                        @Override   //定义成功后返回json数据 ,前后端分离
                        public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
                            response.setContentType("application/json;charset=utf-8");
                            PrintWriter writer = response.getWriter();
                            Map<String,Object> map = new HashMap<>();
                            map.put("status",200);
                            map.put("msg","success");
                            writer.write(new ObjectMapper().writeValueAsString(map)); //将map以json格式输出
                            writer.flush();
                            writer.close();
                        }
                    })
                
                    .failureHandler(new AuthenticationFailureHandler() {
                        @Override //定义失败后的操作(前后端分离)
                        public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
                            response.setContentType("application/json;charset=utf-8");
                            PrintWriter writer = response.getWriter();
                            Map<String,Object> map = new HashMap<>();
                            map.put("status",401);
                            if (e instanceof LockedException){
                                map.put("msg","账户被锁定,登陆失败");
                            }//在lockerException的父类的父类中就有很多异常,如下图,灵活使用
                            writer.write(new ObjectMapper().writeValueAsString(map)); //将map以json格式输出
                            writer.flush();
                            writer.close();
                        }
                    })
                	 .permitAll()   //登录接口对所有人开放
                    .and()
                
                    .logout()
                    .logoutUrl("/logout")
                    .logoutSuccessHandler(new LogoutSuccessHandler() {
                        @Override //注销登录
                        public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
                            response.setContentType("application/json;charset=utf-8");
                            PrintWriter writer = response.getWriter();
                            Map<String,Object> map = new HashMap<>();
                            map.put("status",200);
                            map.put("msg","注销成功");
                            writer.write(new ObjectMapper().writeValueAsString(map)); //将map以json格式输出
                            writer.flush();
                            writer.close();
                        }
                    })
                	.permitAll();
        }
    

    异常

  • 多个HttpSecurity配置(使代码看起来更简洁)

    • @Configuration
      public class Config2 {
      
          @Bean
          PasswordEncoder passwordEncoder(){
              return NoOpPasswordEncoder.getInstance();
          }
      
          @Autowired
          protected void configure(AuthenticationManagerBuilder auth) throws Exception {
              auth.inMemoryAuthentication()
                      .withUser("user").password("123").roles("admin")
                      .and()
                      .withUser("user1").password("123").roles("super");
          }
      
          @Configuration
          @Order(1) //优先级 ,数字越小,级别越高
          public static class AdminSecurityConfig extends WebSecurityConfigurerAdapter(){
              //参考SecurityConfig的配置
          }
      
          @Configuration
          public static class UserSecurityConfig extends WebSecurityConfigurerAdapter(){
              //参考SecurityConfig的配置
          }
      }
       
      
  • 密码加密

    • @Bean
          PasswordEncoder passwordEncoder(){
              return new BCryptPasswordEncoder();
          }
      
    • SpringSecurity使用的密码加密比MD5+盐更加严谨,即使相同的明文,加密的密文也一样,不易被暴力破解,而且不用解决存盐问题,当然,世界上没有绝对的安全加密,只能说更加安全。


    ​ 如果有对你帮助,求点个赞。

posted @ 2020-05-29 18:32  lopzzzzzzzzzzzzzz  阅读(220)  评论(0编辑  收藏  举报