spring security登录认证流程

spring security登录认证流程

1、前端携带用户名和面膜发送请求,controller接收到后,调用service的login方法

2、根据传过来的用户名和密码生成UsernamePasswordAuthenticationToken(这个token里面存放了用户名和密码)

UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUserName(),user.getPassword());

3、根据上面获得的token进行认证,如果认证失败为空,否则获取认证对象authenticate的Principal里面存了这个用户的所有信息。

步骤是:
1、我们需要定义一个类去实现UserDetailsService接口的loadUserByUsername方法
@Service
public class UserDetailsServiceImpl implements UserDetailsService {

@Autowired
private UserMapper userMapper;

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//根据用户名查询用户信息
LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(User::getUserName,username);
User user = userMapper.selectOne(queryWrapper);
//判断是否查到用户 如果没查到抛出异常
if(Objects.isNull(user)){
throw new RuntimeException("用户不存在");
}
//返回用户信息
// TODO 查询权限信息封装
return new LoginUser(user);
}
}

2、在使用authenticationManager.authenticate(authenticationToken);去获取Authentication对象的中间步骤会去调用UserDetailsService的loadUserByUsername去数据库中获取user返回。没有该用户需要抛异常

 

 


3、然后使用additionalAuthenticationChecks的check方法,调用passwordEncoder的matches方法对密码进行校验。matches方法,第一个参数为明文!,第二个参数才是密文 !

 

 match方法

 

 

3、校验失败会抛异常,没有最后就返回Authentication对象(里面存了user信息)。

4、根据上面那个authenticate(认证)对象的getPrincipal获取这个user。然后根据user获取userid

5、使用jwt工具类去根据用户id创建jwt,然后把这个用户的登录信息存入redis。

6、把部分用户信息和jwt返回给前端。

 

 

访问认证流程

1、定义一个SecurityConfig继承WebSecurityConfigurerAdapter,去实现配置哪些需要认证才能访问,并且将自定义的过滤器放入SpringSecurity的过滤器链中.

@Slf4j
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Autowired
private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
@Autowired
AuthenticationEntryPoint authenticationEntryPoint;
@Autowired
AccessDeniedHandler accessDeniedHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
//关闭csrf
.csrf().disable()
//不通过Session获取SecurityContext
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
// 对于登录接口 允许匿名访问
.antMatchers("/login").anonymous()
//注销接口需要认证才能访问
.antMatchers("/logout").authenticated()
//个人信息接口必须登录后才能访问
.antMatchers("/user/userInfo").authenticated()
// 除上面外的所有请求全部不需要认证即可访问
.anyRequest().permitAll();
//配置异常处理器
http.exceptionHandling()
.authenticationEntryPoint(authenticationEntryPoint)
.accessDeniedHandler(accessDeniedHandler);
//关闭默认的注销功能
http.logout().disable();
//把jwtAuthenticationTokenFilter添加到SpringSecurity的过滤器链中
http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
//允许跨域
http.cors();
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}

 

 

2、自定义的过滤器:获取请求头中的token,然后解析出token中的userid(因为这个token是我们通过jwt工具类使用userid生成的)

3、根据这个userid去redis缓存中获取用户,如果没有会抛出用户位登录异常(这个redis会过期)。

4、、然后将这个user放入UsernamePasswordAuthenticationToken authenticationToken(身份验证令牌)中,将这个令牌给(安全上下文持有者)

5、然后放行

posted @ 2022-07-04 20:12  大大怪下士  阅读(3015)  评论(0)    收藏  举报