通过 Angular 5 和 Spring Sec 5 中的 HTTP GET 请求对用户进行身份验证

Posted

技术标签:

【中文标题】通过 Angular 5 和 Spring Sec 5 中的 HTTP GET 请求对用户进行身份验证【英文标题】:Authenticating a user through a HTTP GET request in Angular 5 and Spring Sec 5 【发布时间】:2018-12-24 00:14:30 【问题描述】:

我正在开发一个 Spring Boot 2 + Angular 5 项目。对于那些会认出它的人来说,这是来自 Spring Guides 网站上的 Spring Security and Angular tutorial 的超级灵感。

我有一个使用基本身份验证的安全后端。

@SpringBootApplication
@RestController
public class BasicApplication extends WebSecurityConfigurerAdapter implements WebMvcConfigurer 
    public static void main(String[] args) 
        SpringApplication.run(BasicApplication.class, args);
    

    @GetMapping("/resource")
    public Map<String, Object> home() 
        Map<String, Object> model = new HashMap<>();
        model.put("id", UUID.randomUUID().toString());
        model.put("content", "Hello Spring Security Boot 2 and Angular");
        return model;
    

    @Override
    public void addCorsMappings(CorsRegistry registry) 
        registry.addMapping("/resource")
                .allowedOrigins("http://localhost:4200")
                .allowedMethods("GET");
    

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http
                .authorizeRequests()
                .anyRequest()
                .authenticated()
                .and()
                .httpBasic();
    

当 curl /resource 端点时,我成功

curl http://user:password@localhost:8080/resource

我想使用 Angular 执行完全相同的身份验证之王。所以我实现了以下组件:

import  Component  from '@angular/core';
import  HttpClient, HttpHeaders  from '@angular/common/http';

@Component(
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
)
export class AppComponent 
  title = 'Hello WAT';
  greeting =  id: 'XXX', content: 'Hello World' ;

  constructor(private http: HttpClient) 
    const httpOptions = 
      headers: new HttpHeaders(
        'Content-Type':  'application/json',
        'Authorization': 'user:password'
      )
    ;

    http
      .get<any>('http://localhost:8080/resource', httpOptions)
      .subscribe(resource => (this.greeting = resource));
  

这是我在浏览器日志中的内容:

Access-Control-Request-Headers authorization,content-type

从逻辑上讲,这是 Spring Sec DEBUG 日志所说的:

2018-07-16 14:25:28.355 DEBUG 8792 --- [nio-8080-exec-1] o.s.s.w.a.AnonymousAuthenticationFilter  : Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@9a00c039: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
...
2018-07-16 14:25:28.377 DEBUG 8792 --- [nio-8080-exec-1] w.c.HttpSessionSecurityContextRepository : SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.

【问题讨论】:

通常情况下,在通过标头进行基本身份验证时,user:password 在发送前经过 base64 编码 喜欢'Authorization': btoa('user:password')? 没错。它通常也以“基本”一词为前缀,因此实际值应该类似于"Basic " + btoa('user:password') 首先,感谢您的帮助。我刚刚做了:'Authorization': 'Basic ' + btoa('user:password'),但我仍然没有看到我的标题。日志仍然是:Access-Control-Request-Headers: authorization 运气好吗?现在有效吗? 【参考方案1】:

首先,我必须感谢user184994 的有用评论:添加'Basic ' + btoa(...) 确实有用!

'Authorization': 'Basic ' + btoa('user:password')

接下来,在用各种浏览器测试后,最终偶然发现如下错误信息:

Failed to load http://localhost:8080/resource: Response for preflight has invalid HTTP status code 401.

经过一些研究和摆弄后,我发现将 CORS 配置添加到 Spring Security 可以解决问题。

http
     ...
     .and()
     .cors()

【讨论】:

以上是关于通过 Angular 5 和 Spring Sec 5 中的 HTTP GET 请求对用户进行身份验证的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot - WebLogic 上的 Angular 5 集成

如何通过 POST 从 Angular 5 向 Spring 控制器发送多个 RequestParams

whitelabel 错误页面 404 spring boot angular 5

使用 Spring Boot 和 Angular 提醒推送通知

发布请求不适用于 Spring 安全性和 Angular 5

sec:authorize 不起作用 - Spring Boot 2、Thymeleaf 3、Thymeleaf Spring Security 5 集成包