简体   繁体   English

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

[英]Spring Security authenticate user via post

I have a react app running on a separate port (localhost:3000) that i want to use to authenticate users with, currently i have a proxy setup to my Spring backend (localhost:8080).我有一个在单独的端口 (localhost:3000) 上运行的 React 应用程序,我想用它来验证用户身份,目前我有一个代理设置到我的 Spring 后端 (localhost:8080)。

Can I somehow manually authenticate instead of http.httpBasic() by sending a POST request to my backend and getting back a session cookie then include the cookie with every request?我可以通过向我的后端发送POST请求并取回会话 cookie 然后在每个请求中包含 cookie 来以某种方式手动验证而不是http.httpBasic()吗? It would simplify the auth process on iOS side aswell (using this process i could only store the session cookie value in keychain and pass it with every request made to my api)它也将简化 iOS 端的身份验证过程(使用此过程,我只能将会话 cookie 值存储在钥匙串中,并将其与对我的 api 发出的每个请求一起传递)

How would I disable csrf for non-browser requests?如何为非浏览器请求禁用 csrf?

Is there a better approach to this?有没有更好的方法来解决这个问题? Diffrent paths for browser and mobile auth?浏览器和移动身份验证的不同路径?

 {
   "username": "user",
   "password": "12345678"
 }

Handle the request in spring controller在 spring 控制器中处理请求

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

My WebSecurityConfigurerAdapter.java我的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);
    }
} 

You can create an endpoint that takes user's credentials in a request body, perform authentication and then set tokens, and other required parameters in HttpOnly cookies.您可以创建一个端点,该端点在请求正文中获取用户凭据,执行身份验证,然后在HttpOnly cookie 中设置令牌和其他必需参数。

After setting cookies, subsequent requests can read access/refresh token from cookies and add it in requests, you can then use custom CheckTokenEndpoint to verify tokens.设置 cookie 后,后续请求可以从 cookie 中读取访问/刷新令牌并将其添加到请求中,然后您可以使用自定义CheckTokenEndpoint来验证令牌。

In the following example TokenParametersDto is a POJO that has username and password properties.在以下示例中, TokenParametersDto是一个具有usernamepassword属性的 POJO。

For issuing token (by verifying credentials) you can delegate call to TokenEndpoint#postAccessToken(....) or use its logic to your own method.对于颁发令牌(通过验证凭据),您可以将调用委托给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 for disabling CSRF for a specific URL section.检查此答案以禁用特定 URL 部分的 CSRF。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM