【问题标题】:Spring Boot Security sends 404 although credentials are correct - cant resolve redirect path尽管凭据正确,但 Spring Boot Security 发送 404 - 无法解析重定向路径
【发布时间】:2018-11-10 22:01:42
【问题描述】:

我有一个简单的问题要问你们。如果我在我的 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 代码

网络安全配置

@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);
}

}

UserDetailsS​​erviceImpl

@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());
}

}

也许有人可以帮助我!

【问题讨论】:

  • 您可能需要配置成功转发url。
  • 是否需要重写successauthentication方法?或者哪种方法是正确的?

标签: java spring spring-boot spring-security


【解决方案1】:

我遇到了类似的问题,对我有用的解决方案是像这样覆盖 AbstractAuthenticationProcessingFilter 的成功验证方法

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 中

【讨论】:

  • Java:SecurityContextHolder.getContext().setAuthentication(authResult);
猜你喜欢
  • 1970-01-01
  • 2019-03-26
  • 2017-12-05
  • 2021-01-18
  • 2015-10-31
  • 2018-09-05
  • 2019-08-10
  • 2021-10-13
  • 2012-11-29
相关资源
最近更新 更多