SpringSecurity:认证成功后如何继续向 RestController 转发请求?

Posted

技术标签:

【中文标题】SpringSecurity:认证成功后如何继续向 RestController 转发请求?【英文标题】:SpringSecurity: How to Continue Forwarding Request to RestController After a Successful Authentication? 【发布时间】:2020-07-01 08:22:24 【问题描述】:

我正在使用 REST API(不是 MVC)做一个纯后端项目,并希望使用带有 JWT 令牌的 SpringSecurity 来投射这些 API。实现很好,所有 API 都被令牌成功保护,我可以将带有用户名和密码的 JSON 字符串发布到“/login”路径以获取令牌

我的问题是:

SpringSecurity 将直接在successfulAuthentication() 中返回带有令牌的响应,而不是继续转发到RestController(RestController 的“/login”路径没有数据)

我的问题是:

我应该怎么做,成功认证后,让SpringSecurity可以继续将请求转发到RestController的“/login”路径,这样我就可以对请求和路径中的安全性旁边的新构建令牌做其他事情?

感谢任何帮助,谢谢!

我的代码:

@Component
public class TokenWebSecurityConfig extends WebSecurityConfigurerAdapter 
    // ...

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        // ...
        http.authorizeRequests()
                .antMatchers("/registry").permitAll()         // allow path /registry
                .antMatchers("/login").permitAll()            // allow path /login
                .antMatchers("/verify").permitAll()           // allow path /verify
                .anyRequest().authenticated();
        // ...
    



@RestController
public class EntranceEndpoint 

    @RequestMapping(path = "/login", method = RequestMethod.POST)
    public RestResponse<String> login(LoginMetaInfo login) 
        System.out.println(login);  // no output here when login

        // some further operations for a successful login, and return a REST response
    

这就是 SpringSecurity 在成功登录时所做的事情

public class TokenLoginFilter extends UsernamePasswordAuthenticationFilter 
    // ...
    /**
     * on login success
     */
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication auth) throws IOException 

        // here build the token and insert into response for commitment
        // - the SpringSecurity soon returns the response directly, rather then keep forwarding to RestController
        String token = xxxx;
        response.setStatus(StatusCode.SUCCESS().getCode());
        RestResponse<String> body = RestResponse.succeeded(StatusCode.SUCCESS().withMsg(LoginResponseCode.LOGIN), token);
        response.setContentType(MediaType.APPLICATION_JSON);
        response.setCharacterEncoding(MediaType.CHARSET);
        ObjectMapper mapper = new ObjectMapper();
        mapper.writeValue(response.getWriter(), body );
    

【问题讨论】:

我认为您不应该在响应中写入值。相反,您可以将值放在请求或会话属性中,然后在EntranceEndpoint 中使用它。另外,successfulAuthentication 方法的目的是在安全上下文中设置一个经过身份验证的用户——你不需要在这里做任何额外的事情。 【参考方案1】:

如果简单地使用 HttpServletResponse 的 sendRedirect 而不是写入响应呢?

   @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication auth) throws IOException 

      // do what you want here

        response.sendRedirect("/login");
         // response.sendRedirect("https://yoururl");
    

【讨论】:

以上是关于SpringSecurity:认证成功后如何继续向 RestController 转发请求?的主要内容,如果未能解决你的问题,请参考以下文章

Spring Security 认证成功后返回匿名用户

Springboot和Spring Security中认证成功后如何授权Rest API调用

SpringSecurity-9-实现通过手机短信进行认证功能

Spring认证执行了两次,先成功后失败

Spring Security中的自动登录

SpringSecurity原理解析