[英]spring security + jwt loadUserByUsername not call
[安全配置]
@Slf4j
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private final AuthenticationConfiguration authenticationConfiguration;
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
httpSecurity
.cors()
.and()
.csrf().disable()
.formLogin().disable()
.httpBasic().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
/*.headers().disable()*/
.anyRequest().permitAll()
.and()
.addFilterBefore(new JwtAuthenticationFilter(authenticationManager(authenticationConfiguration)), UsernamePasswordAuthenticationFilter.class);
return httpSecurity.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
[JwtAuthenticationFilter]
@RequiredArgsConstructor
@Slf4j
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private final AuthenticationManager authenticationManager;
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
log.info("Check Run");
ObjectMapper om = new ObjectMapper();
try {
AdvertiserUserDto.Read read = om.readValue(request.getInputStream(), AdvertiserUserDto.Read.class);
UsernamePasswordAuthenticationToken authenticationToken
= new UsernamePasswordAuthenticationToken(read.getUserLoginId(), read.getPassword());
log.info(authenticationToken.getPrincipal().toString());
log.info(authenticationToken.getCredentials().toString());
return authenticationManager.authenticate(authenticationToken);
}
catch (IOException e) {
e.printStackTrace();
log.error("IO Exception");
}
return null;
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
log.info("Success");
super.successfulAuthentication(request, response, chain, authResult);
}
@Override
protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException {
log.info("Fail");
super.unsuccessfulAuthentication(request, response, failed);
}
}
[安全用户详细信息服务]
@Slf4j
@RequiredArgsConstructor
@Service
public class SecurityUserDetailsService implements UserDetailsService {
private final UserRepository userRepository;
@Transactional
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
log.info("loadUserByUsername"); // **not Run**
UserEntity user = userRepository.findByUserLoginId(username).orElseThrow(() -> new UsernameNotFoundException("no Search User"));
return new SecurityUserDetails(
user,
/*Collections.singleton(new SimpleGrantedAuthority("ROLE_" + user.getType().getRoll()))*/
Collections.singleton(new SimpleGrantedAuthority("ROLE_" + "USER"))
);
}
}
[安全用户详细信息]
@RequiredArgsConstructor
@Data
public class SecurityUserDetails implements UserDetails {
private final UserEntity user;
private final Collection<? extends GrantedAuthority> authorities;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public String getUsername() {
return user.getUserId().toString();
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
请注意,我在一个非常基本的水平上挣扎。
这是我到目前为止尝试过的过程:
登录尝试(用户,密码)
安全链被执行
执行一个继承自 UsernamePasswordAuthenticationFilter 的过滤器
已确认 ID 和 PW 正常作为参数传递。
执行AuthenticationManager的authenticate()方法检查ID和PW是否正确。
继承UserDeatilsService的loadUserByUsername()方法没有执行,立即执行unsuccessfulAuthentication()方法失败。
我附上代码。
根据我的计划,验证应该通过 loadUserByUsername() 来完成。
但是为什么验证工作没有执行就立即失败呢?
结果:
c.b.k.c.c.t.JwtAuthenticationFilter : Check Run
c.b.k.c.c.t.JwtAuthenticationFilter : test
c.b.k.c.c.t.JwtAuthenticationFilter : 1234
c.b.k.c.c.t.JwtAuthenticationFilter : Fail
我回答自己是如何找到它的。
@Slf4j
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
private final SecurityUserDetailsService securityUserDetailsService;
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
return authenticationConfiguration.getAuthenticationManager();
}
@Bean
public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception {
AuthenticationManagerBuilder authenticationManagerBuilder = httpSecurity.getSharedObject(AuthenticationManagerBuilder.class);
authenticationManagerBuilder.userDetailsService(securityUserDetailsService);
AuthenticationManager authenticationManager = authenticationManagerBuilder.build();
httpSecurity
.cors()
.and()
.csrf().disable()
.formLogin().disable()
.httpBasic().disable()
.authenticationManager(authenticationManager)
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
/*.headers().disable()*/
.anyRequest().permitAll()
.and()
.addFilterBefore(new JwtAuthenticationFilter(authenticationManager), UsernamePasswordAuthenticationFilter.class);
return httpSecurity.build();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
以下是我如何通过其他建议发现并成功的。
我认为这种方法存在一些问题或需要改进的地方。
我不知道这是否是正确的方法,但我正在为他人和改进而写下来。
AuthenticationManagerBuilder authenticationManagerBuilder = httpSecurity.getSharedObject(AuthenticationManagerBuilder.class);
authenticationManagerBuilder.userDetailsService(securityUserDetailsService);
AuthenticationManager authenticationManager = authenticationManagerBuilder.build();
关键在这里。
我解决了这个问题,因为无法将我自定义和扩展的 userDetatilsService 通知(无法注入)到 AuthenticationManager。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.