一、Spring Security之数据库验证源码解析

    xiaoxiao2023-11-17  136

    一、源码调用流程图

    备注:认证的请求方法必须为POST!!!

    上图的核心思想如下:

    AbstractAuthenticationProcessingFilter#doFilter() UsernamePasswordAuthenticationFilter#attemptAuthentication() ProviderManager#authenticate() AbstractUserDetailsAuthenticationProvider#authenticate() DaoAuthenticationProvider#retrieveUser() UserDetailsService#loadUserByUsername()

    详情解析,参见Spring-Security-入门(二):基于数据库验证   而与我们项目有关的就是,自定义实现UserDetailsService接口的loadUserByUsername()方法,在这里我们将从数据库中读取到的用户信息,主要是用户名、密码、权限集合构建UserDetails对象供框架比对我们前台输入的用户名、密码进行验证。案例如下: 1.DbUserDetailService   自定义实现UserDetailsService接口的loadUserByUsername()方法,在这里我们将从数据库中读取到的用户信息,主要是用户名、密码、权限集合构建UserDetails对象供框架比对我们前台输入的用户名、密码进行验证。

    package com.example.config; import com.example.entity.User; import com.example.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; /** * @author 咸鱼 * @date 2019-05-25 21:47 */ @Service public class DbUserDetailService implements UserDetailsService { // 自定义Service,实现与数据库的交互 private UserService userService; @Autowired public DbUserDetailService(UserService userService) { this.userService = userService; } @Override public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { //1.查询数据库 User user = userService.findUserByName(s); if (user == null) { throw new UsernameNotFoundException("用户不存在!"); } //2.权限集合(一般也是从数据库查询,这里简化,直接赋值) List<GrantedAuthority> grantedAuthorities = new ArrayList<>(); grantedAuthorities.add(new SimpleGrantedAuthority("USER")); //3.用户名、密码、权限集合 构建UserDetails对象 return new org.springframework.security.core.userdetails.User(user.getUsername(), user.getPassword(), grantedAuthorities); } }

    2.WebSecurityConfig   配置验证规则、UserDetailsService 实现类和密码编码规则

    package com.example.config; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.password.NoOpPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; /** * @author 咸鱼 * @date 2019-05-25 21:43 */ @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter { /** * 注入 {@link UserDetailsService} 实现类 */ private DbUserDetailService dbUserDetailService; @Autowired public WebSecurityConfig(DbUserDetailService dbUserDetailService) { this.dbUserDetailService = dbUserDetailService; } /** * 配置验证规则 */ @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests() .antMatchers("/").permitAll() .antMatchers("/user/**").hasAuthority("USER") .and() .formLogin().loginPage("/login").defaultSuccessUrl("/user") .and() .logout().logoutUrl("/logout").logoutSuccessUrl("/login"); } /** * 配置{@link UserDetailsService}的实现类 */ @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(dbUserDetailService); } /** * 密码加密,必须为 @Bean ,否则报错 */ @Bean public static PasswordEncoder passwordEncoder() { return NoOpPasswordEncoder.getInstance(); } }

    3.通过验证的用户,如何取出用户信息

    package com.example.controller; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; import java.security.Principal; /** * @author 咸鱼 * @date 2019-05-25 22:25 */ @Controller public class UserController { /** * @AuthenticationPrincipal Principal principal:这里记录用户信息 */ @GetMapping("/user") public String user(@AuthenticationPrincipal Principal principal, Model model) { model.addAttribute("username", principal.getName()); return "/user/user"; } }

    权限控制的核心代码就是上线这一块!

    最新回复(0)