我为你们解决了一个简单的问题。我面临的问题是,如果我在Spring Boot应用程序中实现Spring Security,我总会收到404响应。
我通过整个代码进行了调试,我发现重定向路径始终是“/”而不是被调用的URL。
例如
call localhost:8080/user/login/
-> Spring Security check given credentials
-> they are correct
-> resolve given path
-> SOMETHING STANGES HAPPENS HERE (Refer to figure (1))
-> resolve path to "/" and not "/user/login/"
-> Therefore I get the response 404 NOT FOUND because it returns the wrong path
调试模式 - determineTargetUrl - > this.targetUrlParameter未设置,因此targetUrl将为“/”而不是 real targetUrl“/ user / login /”。代码如图(1)所示。
图(1)Spring Secutiry类 - AbstractAuthenticationTargetUrlRequestHandler
我的Spring Security代码
WebSecurityConfig
@EnableWebSecurity
公共类WebSecurityConfig扩展了WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
.disable()
.csrf()
.disable()
.authorizeRequests()
.antMatchers(HttpMethod.POST, "/user/login/").permitAll()
.antMatchers(HttpMethod.GET, "/user/secret/**").permitAll()
.and()
.addFilterBefore(new JWTLoginFilter("/user/login/", authenticationManager()), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(new JWTAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
}
}
JWTLoginFilter
public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter {
public JWTLoginFilter(String url, AuthenticationManager authManager) {
super(new AntPathRequestMatcher(url));
setAuthenticationManager(authManager);
}
@Override
public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse res) throws AuthenticationException, IOException, ServletException {
User user = new ObjectMapper().readValue(req.getInputStream(), User.class);
Optional<User> dbUser = SpringContextBridge.services().getUserRepository().findUserByEmail(user.getEmail());
dbUser.ifPresent(us -> user.setPassword(SecretGenerator.generateSha256(user.getPassword(), us.getSecret())));
return getAuthenticationManager()
.authenticate(new UsernamePasswordAuthenticationToken(user.getEmail(), user.getPassword(), Collections.emptyList())
);
}
}
JWTAuthenticationFilter
public class JWTAuthenticationFilter extends GenericFilterBean {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
Authentication authentication = TokenAuthenticationService.getAuthentication((HttpServletRequest) request);
SecurityContextHolder.getContext().setAuthentication(authentication);
filterChain.doFilter(request, response);
}
}
UserDetailsServiceImpl
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
private UserRepository userRepository;
@Autowired
public void setUserRepository(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException {
Optional<User> user = userRepository.findUserByEmail(email);
if (!user.isPresent()) {
throw new UserNotFoundException("User with email: " + email + " not found");
}
return new org.springframework.security.core.userdetails.User(user.get().getEmail(), user.get().getPassword(), Collections.emptyList());
}
}
也许有人可以帮助我!
答案 0 :(得分:0)
我有一个类似的问题,对我有用的解决方案是像这样重写AbstractAuthenticationProcessingFilter的successAuthentication方法
override fun successfulAuthentication(request: HttpServletRequest, response: HttpServletResponse, chain: FilterChain, authResult: Authentication?) {
logger.info("Successful Authentication for user ${authResult?.principal}")
SecurityContextHolder.getContext().authentication = authResult
chain.doFilter(request, response)
}
注意:该示例在kotlin中