Spring Security 通过 post 对用户进行身份验证

Posted

技术标签:

【中文标题】Spring Security 通过 post 对用户进行身份验证【英文标题】:Spring Security authenticate user via post 【发布时间】:2019-12-26 11:19:54 【问题描述】:

我有一个在单独的端口 (localhost:3000) 上运行的 react 应用程序,我想用它来验证用户身份,目前我有一个代理设置到我的 Spring 后端 (localhost:8080)。

我是否可以通过向我的后端发送 POST 请求并取回会话 cookie 然后在每个请求中包含该 cookie 以某种方式手动验证而不是 http.httpBasic()?它还将简化 ios 端的身份验证过程(使用此过程,我只能将会话 cookie 值存储在钥匙串中,并将其与对我的 api 的每个请求一起传递)

如何为非浏览器请求禁用 csrf?

有没有更好的方法来解决这个问题?浏览器和移动身份验证的不同路径?

 
   "username": "user",
   "password": "12345678"
 

在spring控制器中处理请求

@PostMapping(path = "/web")
public String authenticateUser() 
    //Receive the auth data here... and perform auth
    //Send back session cookie
    return "Success?";

我的 WebSecurityConfigurerAdapter.java

@Configuration
@EnableWebSecurity
public class WebsecurityConfig extends WebSecurityConfigurerAdapter 
    private final DetailService detailService;

    public WebsecurityConfig(DetailService detailService) 
        this.detailService = detailService;
    

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception 
        auth.userDetailsService(detailService).passwordEncoder(passwordEncoder());
    

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http
                .httpBasic().disable()
                .authorizeRequests()
                .antMatchers(HttpMethod.POST,"/api/v1/authenticate/new").permitAll()
                .antMatchers(HttpMethod.POST,"/api/v1/authenticate/web").permitAll()
                .anyRequest().authenticated();

    

    @Bean
    public WebMvcConfigurer corsConfigurer() 
        return new WebMvcConfigurer() 
            @Override
            public void addCorsMappings(CorsRegistry registry) 
                registry.addMapping("/**").allowedMethods("GET", "POST").allowedOrigins("http://localhost:8080");
            
        ;
    

    @Bean
    public PasswordEncoder passwordEncoder() 
        return new BCryptPasswordEncoder(14);
    
 

【问题讨论】:

我认为对于非浏览器客户端,您可以实现基于 Spring 安全令牌的身份验证机制。 ***.com/questions/17126201/… 您可以通过 JWT 使用基于令牌的机制。 ***.com/questions/49325692/… @ShanmugaSundaramN JWT 不适用于会话 【参考方案1】:

您可以创建一个端点,在请求正文中获取用户凭据,执行身份验证,然后在 HttpOnly cookie 中设置令牌和其他必需参数。

设置cookies后,后续请求可以从cookies中读取access/refresh token并将其添加到请求中,然后可以使用自定义CheckTokenEndpoint来验证tokens。

在以下示例中,TokenParametersDto 是一个 POJO,具有 usernamepassword 属性。

对于颁发令牌(通过验证凭据),您可以将调用委托给 TokenEndpoint#postAccessToken(....) 或将其逻辑用于您自己的方法。

@PostMapping(path = "/oauth/http/token", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<Void> issueToken(@RequestBody final @Valid @NotNull TokenParametersDto tokenParametersDto,
                                       final HttpServletResponse response) 

    final OAuth2AccessToken token = tokenService.issueToken(tokenParametersDto);

    storeTokenInCookie(token, response);

    return new ResponseEntity<>(HttpStatus.OK);


private void storeTokenInCookie(final OAuth2AccessToken token, final HttpServletResponse response) 
    final Cookie accessToken = new Cookie("access_token", token.getValue());
    accessToken.setHttpOnly(true);
    accessToken.setSecure(sslEnabled);
    accessToken.setPath("/");
    accessToken.setMaxAge(cookieExpiration);

    final Cookie tokenType = new Cookie("token_type", token.getTokenType());
    tokenType.setHttpOnly(true);
    tokenType.setSecure(sslEnabled);
    tokenType.setPath("/");
    tokenType.setMaxAge(cookieExpiration);

    // Set Refresh Token and other required cookies.

    response.addCookie(accessToken);
    response.addCookie(tokenType);

Check this answer 用于禁用特定 URL 部分的 CSRF。

【讨论】:

以上是关于Spring Security 通过 post 对用户进行身份验证的主要内容,如果未能解决你的问题,请参考以下文章

Java Spring Security OAuth2:通过 POST 接受客户端凭据

Spring Security OAuth2-对 oauth/token 的 POST 请求重定向到登录和角色显示 ROLE_ANONYMOUS

前后端分离 Spring Security 对登出.logout()的处理

前后端分离 Spring Security 对登出.logout()的处理

Spring Security + REST 控制器 Post 方法不显示用户名

Spring Security 和 JSON 身份验证