【问题标题】:SESSIONID is not getting stored in Cookie in an application with Angular 6 as frontend and spring boot as backend [closed]SESSIONID 未存储在以 Angular 6 作为前端、Spring Boot 作为后端的应用程序的 Cookie 中[关闭]
【发布时间】:2020-05-19 13:44:42
【问题描述】:

我正在建立一个简单的问答网站。前端是 Angular 6,后端是 Spring Boot。我还在使用 Spring Security 和 Redis 来存储会话。我有几个问题。

  1. 当用户登录时,我看到来自服务器的响应在响应标头中包含 SetCookie: Session: XXXXX,但在随后的调用中,从未在 HEADER 中设置会话属性。我还在 Chrome 的检查模式下检查了应用程序选项卡中的 Cookie。未设置任何值。但是,如果我在 localStorage 中设置任何内容。我可以在那里看到它。

登录代码

login.component.ts (This is called once the user press login)

       this.authenticationService.login(this.f.email.value, this.f.password.value)
            .pipe(first())
            .subscribe(
                data => {
                    // this.router.navigate([this.returnUrl]);
                    this.router.navigate(['/home']);
                },
                error => {
                    this.alertService.error(error);
                    this.loading = false;
                });


AuthenticationService


export class AuthenticationService {
    constructor(private http: HttpClient) { }

    login(emailId: string, password: string) {


        const headers = new HttpHeaders(
            emailId && password ? {
              authorization:'Basic ' + btoa(emailId + ':' + password)
            }:{}
          );

        return this.http.get<any>(`${environment.apiUrl}/users/login`, {headers:headers})
            .pipe(map(user => {

                if (user ) { 

                    localStorage.setItem('currentUser', JSON.stringify(user));
                    console.log("user is " + JSON.stringify(user));
                }

                return user;
            }));
    }


SpringBoot

 @Override
    protected void configure(HttpSecurity http) throws Exception {
        logger.info("*********Authorizing in websecurityconfig*********");
        http.cors().and()
                //starts authorizing configurations
                .authorizeRequests()
                //ignoring the guest urls...
                .antMatchers("/resources/**", "/error","/users/**").permitAll()
                .anyRequest().fullyAuthenticated()
                .and()
                .logout().permitAll()
                .logoutRequestMatcher(new AntPathRequestMatcher("/users/logout", "POST"))
                .and()
                .formLogin().loginPage("/users/login").and()
                .httpBasic().and()
                .csrf().disable();
    }




REST API

  @CrossOrigin
    @GetMapping("/login")
    public ResponseEntity<?>  getStudentDetailById (Principal principal) throws Exception{

        final String emailId = principal.getName();
        try {
            ValidationUtil.validate(emailId);
            logger.info("Email id is " + emailId);
        } catch (InvalidArgumentException e) {
            logger.info("Exception = {} occurred", e);
        }

        return ResponseEntity.ok(principal.getName());
    }

这是从服务器收到的登录响应中的 SESSION

设置 Cookie:SESSION=YjBjODE2MjQtMGQxOC00ZmU1LWI2MmMtOTg5YzkwM2FjY2Fm;路径=/; HttpOnly

登录后,假设我想在同一台服务器/另一台服务器上调用另一个 API。该请求不包含会话详细信息。

我错过了什么。

  1. 我想澄清一下收到的 SESSIONID 的功能和将用户 ID 存储在 localStorage 中的优势。

我的问题

我想在用户登录后获取他/她发布的问题。因此,我需要他/她的用户 ID 在登录后的响应中。因此,登录后,我将用户 ID 存储在 localStorage 中。那么SESSIONID有什么用呢?是否只是为了确保对服务器的后续请求不必一次又一次地进行身份验证,因为 Spring Security 将使用 SESSIONID 来允许用户使用其他资源。如果是,那么 Spring Security 是否会验证每个 SESSIONID 请求(我认为是这样)。

【问题讨论】:

  • 您是否在同一台服务器上为 Angular 和 Spring 提供服务?例如。 Spring 是在为您的静态 Angular 构建提供服务,还是从不同的服务器提供 Angular 构建?
  • @NateVaughan 都在不同的服务器上运行。角度:本地主机:4200 SpringBoot:本地主机:8080

标签: angular spring spring-boot spring-security redis


【解决方案1】:

这是我给你的答案。

在浏览器中设置 cookie

如果您希望浏览器在收到响应中的 Set-Cookie 标头时创建 cookie,您可能需要告诉浏览器准备好接受这种行为。默认情况下,如果您的浏览器不应该存储 Cookie,则它不会存储。你必须这样改成get

return this.http.get<any>(`${environment.apiUrl}/users/login`, {headers:headers, withCredentials: true})

完成此操作后,有两种可能的情况:

  • 您的前端和后端共享同一个根目录(例如http://localhost),那么您应该很好,不必担心CORS...
  • 或者,您的前端 URL 是 http://myfrontend.com/,后端是 http://mybackend.com,在这种情况下,您将体验到浏览器发出的 preflight 请求,以及一些 CORS问题,您的后端服务器会自动启用以避免任何攻击...请参阅:Angular 2 cookie not set

就像您在其中一条评论中所说的那样,您的服务器将希望确保允许请求您的端点的客户端。您可以接受具有全局配置的 CORS Origin 请求:

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**").allowedOrigins("http://localhost:4200").allowCredentials(true);
    }
}

SESSIONID 与 LocalStorage

两者既相似又不同。

类似的:

  • 两者都可用于验证您的用户

不同:

  • 您不会以相同的方式验证用户身份。

会话 ID

它们用于在服务器上存储您的用户信息。基本上,服务器存储一个地图以保持一些上下文:

  • 您是否已通过身份验证?
  • 您是否已执行此操作?
  • 你有什么东西想让我替你保管吗?

但一切都在服务器中......两次执行相同的请求,将调用相同的服务器...这是为了确保您有一个常驻系统,或者您需要部署更多服务,因为突然有一张活动图片...无论如何,这是老派,但是当您知道您的客户端将只与一台服务器通信时工作正常。

SESSION_ID 存储在 cookie 中,只能通过 HTTP 访问,这意味着您无法从您的 javascript 代码中读取 cookie 值...它以这种方式受到保护。负责将 cookie 发送到服务器的是您的浏览器。

每个服务器都有自己的 SESSION 映射实例...它不是共享的,因此 server1 没有与 server2 相同的 SESSION 映射...这在您没有的系统中是一个大问题知道如何同时拥有服务器。

本地存储 适合微服务架构的东西是让客户端可以携带自己的身份验证信息,在Token中。这样,您也可以有 1、2 或 25 个服务器进行通话,您的客户端将以相同的方式进行身份验证。但是这个令牌必须在你每次发送到服务器时发送。现在问题是我如何存储令牌并将其发送到服务器?

您有 2 个选项(甚至更多,但我们只考虑 2 个):

  • 您将其存储在本地存储中:localStorage.setItem('token', JSON.stringify(token));。但是本地存储容易受到 XSS 攻击......黑客可以窃取您的令牌信息,然后使用它来验证网站并为您做事,或访问一些私人数据。 For more information on XSS

所以 localStorage 非常适合存储非敏感用户日期,并使客户端保持其内部状态......但是在存储敏感数据(如令牌)时使用它可能很危险。

解决方案?使用HTTP ONLY cookie 来存储客户端的令牌。它与 SESSION_ID 不同,因为它仍然是您的客户端持有身份验证信息,但它受到保护,不会被任何不良 javascript 代码访问。

希望它能回答你的问题。

【讨论】:

  • 感谢您的回答。第二部分是有道理的。但是,对于使用 withCredentials 后问题的第一部分:true。即使域相同,即 localhost,它也会给 Cors 问题,我已经在控制器中的 API 上使用 @CrossOrigin 注释,不知道为什么。正在努力。
  • 您检查过我在回答的第一部分中发送的链接吗?
  • @TringTring,检查我的更新,看看它是否符合您的需要
  • 我的代码中有 WebMvcConfigurer,但它似乎不起作用。您提供的代码有效。非常感谢
  • 如果对您有用,请标记答案并点赞,这是表示感谢的好方法,它可能对其他人有所帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-30
  • 2021-10-25
  • 2020-11-27
  • 2014-11-02
  • 2014-09-28
  • 2018-12-27
  • 2020-01-01
相关资源
最近更新 更多