使用带有 Spring Boot 和 Angular 5 的 httponly cookie 的 JWT 身份验证

Mih*_*sek 7 java spring jwt spring-boot angular

所以,我正在开发一个需要身份验证的Angular 5应用程序。Angular 应用程序正在从Spring Boot API检索数据。对于身份验证,我将电子邮件和密码发送到 API,如果正确,则将 JWT 令牌发回给我。我读过在 localStorage 中存储令牌不是一个好主意,因为它可以通过 javascript 访问,因此容易受到攻击。因此,我想将 JWT 存储到带有httponly安全标志的cookie 中。

但是,问题是因为 Angular 应用程序和 Spring Boot 应用程序运行在不同的来源上,因此从 Spring 收到的响应无法设置 cookie。

我想知道如何在登录成功时实现这一点,我的 API 为可能存在于另一个域上的 angular 应用程序设置 cookie。

这是我的身份验证资源:

@PostMapping("/login")
    public ResponseEntity<LoginResponse> loginUser(@RequestBody LoginRequest request, HttpServletResponse res) {
        LoginResponse response = new LoginResponse("this_is_my_token");
        Cookie cookie = new Cookie("token", "this_is_my_token");
        cookie.setPath("/");
        cookie.setSecure(true);
        cookie.setHttpOnly(true);
        res.setHeader("Access-Control-Allow-Credentials", "true");
        res.addCookie(cookie);
        return ResponseEntity.ok().body(response);
    }
Run Code Online (Sandbox Code Playgroud)

我还配置了 CORS 过滤器:

@Bean
    public WebMvcConfigurer cors() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                        .allowedOrigins("http://localhost:4200") //current angular host, later will be changed
                        .allowCredentials(true)
                        .allowedHeaders("*");
            }
        };
    }
Run Code Online (Sandbox Code Playgroud)

然后在我的 Angular 应用程序中,我有这个服务:

@Injectable()
export class LoginSerivce {
    private headers: HttpHeaders;

    constructor(private http: HttpClient) {
        this.headers = new HttpHeaders({
            "Content-Type": "application/json",
            "Access-Control-Allow-Credentials": "true"
        });
    }

    public getToken() {
        const data = JSON.stringify({
            email: "test",
            geslo: "Test"
        });
        this.http.post("http://localhost:8080/v1/auth/login",
            data, {headers: this.headers, withCredentials: true})
            .toPromise()
            .then(
                (resp) => {
                    console.log(resp);
                },
                (err) => {
                    console.log("error: ", err);
                }
            );
    }
}
Run Code Online (Sandbox Code Playgroud)