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 }