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 }
原文地址:https://www.cnblogs.com/lxy-java/p/13057449.html