zoukankan      html  css  js  c++  java
  • Springboot之security框架 登录安全验证授权流程

    一、只进行用户验证,不验证密码(UserDetailsService)

      1、导入security依赖(在前端html页面进行一些判断  需导入xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4")

     1 <dependency>
     2     <groupId>org.springframework.boot</groupId>
     3     <artifactId>spring-boot-starter-security</artifactId>
     4 </dependency>
     5 
     6 <dependency>
     7     <groupId>org.thymeleaf.extras</groupId>
     8     <artifactId>thymeleaf-extras-springsecurity5</artifactId>
     9     <version>3.0.4.RELEASE</version>
    10 </dependency>

      2、配置安全认证类

     1 import org.springframework.beans.factory.annotation.Autowired;
     2 import org.springframework.context.annotation.Bean;
     3 import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
     4 import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
     5 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
     6 import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
     7 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
     8 import org.springframework.security.core.userdetails.UserDetailsService;
     9 import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
    10 import org.springframework.security.crypto.password.PasswordEncoder;
    11 import top.xiaoyl.service.CustomUserDetailService;
    12 
    13 @EnableWebSecurity
    14 @EnableGlobalMethodSecurity(prePostEnabled = true)
    15 public class MySecurityConfig extends WebSecurityConfigurerAdapter {
    16 
    17     @Override
    18     protected void configure(HttpSecurity http) throws Exception {
    19         //super.configure(http);
    20         //定制请求的授权规则
    21         http.authorizeRequests().antMatchers("/admin/**","/js/**","/css/**","/images/*","/fonts/**","/**/*.png","/**/*.jpg").permitAll()
    22                 .antMatchers("/","/index.html").permitAll()
    23                .antMatchers("/report").hasRole("USER")
    24                 .and()
    25                 .csrf().ignoringAntMatchers("/druid/*");
    26 
    27 
    28         /*
    29          *  开启自动配置的登陆功能,效果,如果没有登陆,没有权限就会来到登陆页面
    30          *      1、login来到登陆页
    31          *      2、重定向到/login?error表示登陆失败
    32          *      3、更多详细规定
    33          *      4、默认post形式的 /login代表处理登陆
    34          *      5、一但定制loginPage;那么 loginPage的post请求就是登陆
    35          */
    36         http.formLogin().usernameParameter("username").passwordParameter("password")
    37                 .loginPage("/login");
    38 
    39 
    40         /*
    41          *  开启自动配置的注销功能
    42          *      1、访问 /logout 表示用户注销,清空session
    43          *      注销成功会返回 /login?logout 页面;
    44          *      注销成功以后来到首页
    45          */
    46         http.logout().logoutSuccessUrl("/");
    47 
    48 
    49         /*
    50          *  开启记住我功能
    51          *      登陆成功以后,将cookie发给浏览器保存,以后访问页面带上这个cookie,只要通过检查就可以免登录
    52          *      点击注销会删除cookie
    53          */
    54         http.rememberMe().rememberMeParameter("remember");
    57     }
    58 
    59     @Bean
    60     UserDetailsService customUserDetailService() { // 注册UserDetailsService 的bean
    61         return new CustomUserDetailService();
    62     }
    63 
    64     /**
    65      * 认证信息管理
    66      * spring5中摒弃了原有的密码存储格式,官方把spring security的密码存储格式改了
    67      *
    68      */
    69     @Autowired
    70     public void configure(AuthenticationManagerBuilder auth) throws Exception {
    71         auth.userDetailsService(customUserDetailService()) //认证信息存储(自定义)
    72                 .passwordEncoder(passwordEncoder());
    73 //
    74 //        auth.inMemoryAuthentication() //认证信息存储到内存中
    75 //                .passwordEncoder(passwordEncoder())
    76 //                .withUser("user").password(passwordEncoder().encode("123")).roles("USER");
    77 
    78     }
    79 
    80     private PasswordEncoder passwordEncoder() {
    81         return new BCryptPasswordEncoder();
    82     }
    83 
    84 }

      3、自定义用户验证类实现UserDetailsService接口,进行授权验证

     1 @Service
     2 public class CustomUserDetailService implements UserDetailsService {
     3 
     4     @Autowired
     5     private UserService userService;
     6 
     7     @Autowired
     8     HttpServletRequest request;
     9 
    10     @Override
    11     public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
    12         HttpSession session = request.getSession();
    13         User user = userService.getUserByUsername(username);
    14         if(user==null){
    15             session.setAttribute("loginMsg","用户名"+username+"不存在");
    16             throw new UsernameNotFoundException("用户名"+username+"不存在");
    17         }
    18         List<SimpleGrantedAuthority> authorities = new ArrayList<>();
    19         authorities.add(new SimpleGrantedAuthority("USER"));
    20         return new org.springframework.security.core.userdetails.User(user.getUsername(),user.getPassword(),authorities);
    21     }
    22 }

    二、进行用户密码验证(AbstractUserDetailsAuthenticationProvider)

      第一种方法虽然也能认证授权,但是问题显而易见,没有进行密码验证,主要用户名对了  就给权限  这很危险

      流程跟一基本一样

      1、导入依赖

      2、配置安全认证类,需要报红色的地方修改一下

     1 @Bean
     2     AbstractUserDetailsAuthenticationProvider customAuthenticationProvide() { // 注册AbstractUserDetailsAuthenticationProvider的bean
     3         return new CustomAuthenticationProvider();
     4     }
     5  
     6 @Autowired
     7     public void configure(AuthenticationManagerBuilder auth) throws Exception {
     8         auth.authenticationProvider(customAuthenticationProvide()); //认证信息存储(自定义)
     9 //
    10 //        auth.inMemoryAuthentication() //认证信息存储到内存中
    11 //                .passwordEncoder(passwordEncoder())
    12 //                .withUser("user").password(passwordEncoder().encode("123")).roles("USER");
    13 
    14     }

      3、自定义用户验证类实现AbstractUserDetailsAuthenticationProvider类,进行授权验证

     1 import org.springframework.beans.factory.annotation.Autowired;
     2 import org.springframework.security.authentication.BadCredentialsException;
     3 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
     4 import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
     5 import org.springframework.security.core.AuthenticationException;
     6 import org.springframework.security.core.authority.SimpleGrantedAuthority;
     7 import org.springframework.security.core.userdetails.UserDetails;
     8 import org.springframework.security.core.userdetails.UsernameNotFoundException;
     9 import org.springframework.stereotype.Service;
    10 import top.xiaoyl.entities.User;
    11 
    12 import javax.servlet.http.HttpServletRequest;
    13 import javax.servlet.http.HttpSession;
    14 import java.util.ArrayList;
    15 import java.util.List;
    16 
    17 @Service
    18 public class CustomAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
    19 
    20     @Autowired
    21     private UserService userService;
    22 
    23     @Autowired
    24     private HttpServletRequest request;
    25 
    26     @Override
    27     protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
    28 
    29     }
    30 
    31     @Override
    32     protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
    33         System.out.println("retrieveUser");
    34         HttpSession session = request.getSession();
    35         if(username==null || username.length()==0){
    36             session.setAttribute("loginMsg","用户名不能为空");
    37             throw new UsernameNotFoundException("用户名不能为空");
    38         }
    39         User user = userService.getUserByUsername(username);
    40         if(user==null){
    41             session.setAttribute("loginMsg","用户名"+username+"不存在");
    42             throw new UsernameNotFoundException("用户名"+username+"不存在");
    43         }
    44         if(!authentication.getCredentials().toString().equals(user.getPassword())){
    45             session.setAttribute("loginMsg","密码不正确");
    46             throw new BadCredentialsException("密码不正确");
    47         }
    48         List<SimpleGrantedAuthority> authorities = new ArrayList<>();
    49         authorities.add(new SimpleGrantedAuthority("USER"));
    50         return new org.springframework.security.core.userdetails.User(user.getUsername(),user.getPassword(),authorities);
    51     }
    52 }
  • 相关阅读:
    年轻人的第一个 Spring Boot 应用,太爽了!
    面试问我 Java 逃逸分析,瞬间被秒杀了。。
    Spring Boot 配置文件 bootstrap vs application 到底有什么区别?
    坑爹的 Java 可变参数,把我整得够惨。。
    6月来了,Java还是第一!
    Eclipse 最常用的 10 组快捷键,个个牛逼!
    Spring Cloud Eureka 自我保护机制实战分析
    今天是 Java 诞生日,Java 24 岁了!
    厉害了,Dubbo 正式毕业!
    Spring Boot 2.1.5 正式发布,1.5.x 即将结束使命!
  • 原文地址:https://www.cnblogs.com/lxy-java/p/13057449.html
Copyright © 2011-2022 走看看