目录

SpringSecurity认证授权完整流程

目录

SpringSecurity认证授权完整流程

SpringSecurity认证流程:loadUserByUsername()方法内部实现。 实现步骤:

  1. 构建一个自定义的service接口,实现SpringSecurity的UserDetailService 接口。
  2. 建一个service实现类,实现此loadUserByUsername方法。
  3. 调用登录的login接口,会经过authenticationManager.authenticate(authenticationToken)方法。此方法会调用loadUserByUsername 方法。
  4. 方法内部做用户信息的查询,判断用户名和密码是否正确,这是第一道认证。 @Service @RequiredArgsConstructor public class UserDetailsServiceImpl implements UserDetailsService { private final SysUserMapper sysUserMapper; //用户登录请求/login,自动调用方法 //根据用户名获取用户信息 //UserDetails 存储用户信息,包括用户名,密码,权限 @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(SysUser::getUsername, username); SysUser sysUser = sysUserMapper.selectOne(wrapper); if (Objects.isNull(sysUser)){ throw new UsernameNotFoundException(“用户名不存在”); } //认证成功回UserDetails对象 return new LoginUser(sysUser); } } https://i-blog.csdnimg.cn/img_convert/32fc0304261a5d87d64d709b73e5f67f.png @ToString public class LoginUser implements UserDetails { private SysUser sysUser; public LoginUser(SysUser sysUser) { this.sysUser = sysUser; } // 权限 @Override public Collection extends GrantedAuthority getAuthorities() { return List.of(); } @Override public String getPassword() { return sysUser.getPassword(); } @Override public String getUsername() { return sysUser.getUsername(); } // 账号是否过期 @Override public boolean isAccountNonExpired() { return true; } // 账号是否被锁定 @Override public boolean isAccountNonLocked() { return true; } // 密码是否过期 @Override public boolean isCredentialsNonExpired() { return true; } // 账号是否可用 @Override public boolean isEnabled() { return true; } } 5.如果没有查到信息就抛出异常。 6.如果查到信息了再接着查用户的权限信息,返回权限信息到loginUser实体。 7.此实体实现了SpringSecurity自带的userDetail 接口。实现了getAuthorities 方法。 .8每次查询权限都会调用此方法。 9.查询到的权限,会被返回到login接口。进行后续操作。 10.如果认证通过,通过身份信息中的userid生产一个jwt。 11.把完整的用户信息作为value,token作为key存入redis。 @RestController @Tag(name = “认证模块”, description = “认证模块”) @RequestMapping("/auth") @RequiredArgsConstructor public class AuthController { //注入AuthenticationManager(认证管理器) private final AuthenticationManager authenticationManager; private final JwtUtils jwtUtils; @PostMapping("/login") @Operation(summary = “登录”) public Result login(@RequestParam(“username”) String username, @RequestParam(“password”) String password) { System.out.println(username + password); //登录逻辑 //调用UserDetailsService.loadUserByUsername方法获取 //不能直接调用,需要通过AuthenticationManager进行认证 Authentication authentication = new UsernamePasswordAuthenticationToken(username, password); Authentication authenticate = null; try { authenticate = authenticationManager.authenticate(authentication); } catch (BadCredentialsException e) { return Result.failed(ResultCode.USERNAME_OR_PASSWORD_ERROR); } //认证成功方法token String token=jwtUtils.generateToken(authenticate); return Result.success(token); } } https://i-blog.csdnimg.cn/img_convert/ab9331090ae36d833e70f88bfe533124.png @Configuration @EnableWebSecurity // 开启web安全 @EnableMethodSecurity @RequiredArgsConstructor public class SecurityConfig { private final IgnoredUrl ignoredUrl; /**
  • 配置认证管理器 AuthenticationManager
  • 作用:用于身份认证
  • 参数:UserDetailsService, PasswordEncoder / @Bean public AuthenticationManager authenticationManager(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) { DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setUserDetailsService(userDetailsService); provider.setPasswordEncoder(passwordEncoder); return new ProviderManager(provider); } /*
  • 密码编码器
  • @return / @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { //关闭csrf防护,否则回导致登录失败 http.csrf(a -> a.disable()); //禁用SCRF //配置安全拦截规则 http.authorizeHttpRequests(req -> req.requestMatchers(ignoredUrl.getUrls()) .permitAll() .anyRequest().authenticated()); /*
  • 配置登录页 / http.formLogin(form -> form .loginPage("/") .successForwardUrl("/index") //登录成功跳转页面 .loginProcessingUrl("/login")//登录处理url .failureForwardUrl("/error") //登录失败跳转页面 // .usernameParameter(“name”)//自定义用户名参数 // .passwordParameter(“password”)//自定义密码参数 ); return http.build(); } } @Component public class JwtUtils { @Value("${jwt.secret}") private String secret; @Value("${jwt.expiration}") private Integer expiration; /*

*/ public String generateToken(Authentication authentication) { Date now = new Date(); Date expirationDate = DateUtil.offsetSecond(now, expiration); Map claims = new HashMap<>(); claims.put(“username”, authentication.getName());//用户名 claims.put(“exp”, expirationDate); // claims.put(); return JWTUtil.createToken(claims, secret.getBytes()); } } @Component @Data @ConfigurationProperties(prefix = “security.ignored”) @ToString public class IgnoredUrl { private String[] urls; } https://i-blog.csdnimg.cn/img_convert/5ec173b2e4e6088915e0380df271abff.png 登录成功 https://i-blog.csdnimg.cn/img_convert/41fcbadfc9a872dc722e82a3c8410da0.png 登陆失败 https://i-blog.csdnimg.cn/img_convert/fde57947d754d23b11db4f8962bf8cb2.png