【问题标题】:Authorization header not working for angular 2授权标头不适用于角度 2
【发布时间】:2018-04-13 14:48:28
【问题描述】:

您好,我正在使用带有 Angular 的 Ionic 2 框架,我想使用授权标头发出 http 请求,但它似乎没有发送标头。我做错了什么?

    @Injectable()
export class UserServiceProvider {
  private loginSuccess: any;
  constructor(public http: Http) {
    console.log('Hello UserServiceProvider Provider');
  }

  login(username, password)
  {
     var token = btoa(username + ':' + password);
     alert(token);
     this.loginSuccess = false;
     let headers = new Headers();
     headers.append('Authorization', 'Basic ' + token);
     this.http.get('http://localhost:8080/HelloWorld/api/login/try', {
         headers: headers
     })
     .subscribe(function success(response) {
        this.loginSuccess = true;
     }, function error(response) {
        this.loginSuccess = false;
     });

     return this.loginSuccess;
  }
}

这是浏览器控制台中的响应

polyfills.js:3 OPTIONS http://localhost:8080/HelloWorld/api/login/try 401 ()
s @ polyfills.js:3
t.scheduleTask @ polyfills.js:3
onScheduleTask @ polyfills.js:3
t.scheduleTask @ polyfills.js:3
r.scheduleTask @ polyfills.js:3
r.scheduleMacroTask @ polyfills.js:3
(anonymous) @ polyfills.js:3
o.(anonymous function) @ polyfills.js:2
(anonymous) @ http.es5.js:1275
Observable._trySubscribe @ Observable.js:171
Observable.subscribe @ Observable.js:159
webpackJsonp.197.UserServiceProvider.login @ user-service.ts:29
webpackJsonp.196.AccountPage.login @ account.ts:21
(anonymous) @ AccountPage.html:25
handleEvent @ core.es5.js:12022
callWithDebugContext @ core.es5.js:13486
debugHandleEvent @ core.es5.js:13074
dispatchEvent @ core.es5.js:8615
(anonymous) @ core.es5.js:9226
(anonymous) @ platform-browser.es5.js:2651
t.invokeTask @ polyfills.js:3
onInvokeTask @ core.es5.js:3881
t.invokeTask @ polyfills.js:3
r.runTask @ polyfills.js:3
e.invokeTask @ polyfills.js:3
p @ polyfills.js:2
v @ polyfills.js:2

(index):1 加载失败 http://localhost:8080/HelloWorld/api/login/try: 预检响应 具有无效的 HTTP 状态代码 401

【问题讨论】:

  • @Deniel McCarthy :附上正在发送到服务器的请求的屏幕截图。还有一点,你好像在登录,如果是这样,那么登录时最常用的方法是 POST 而不是 GET。
  • 我已将回复添加到我认为 POST 或 GET 不会产生影响的帖子中。这不是 HTML 表单,这是 Http 基本身份验证
  • 请检查 CORS 问题,因为预检失败。
  • @DanielMcCarthy 请检查我编辑的答案,其中我添加了过滤方法来克服 CORS 问题。
  • 问题中显示的错误消息是针对浏览器在尝试从您的代码发出 GET 请求之前自动发送的 CORS 预检选项的响应。 CORS 协议要求预检 OPTIONS 请求中不包含任何凭据,因此浏览器不会从您的代码中发送 Authorization 标头。但是您发送该请求的服务器配置错误,即使对于 OPTIONS 请求也需要身份验证。所以服务器发送一个 401 响应拒绝请求并且预检失败并且浏览器停在那里并且永远不会尝试您的 GET。

标签: angular ionic-framework cors http-authentication preflight


【解决方案1】:

以下是我用于登录的项目的示例代码。请参阅相同的登录。请检查web服务中的登录功能是GET还是POST。

public postOAuthRequest(login:Login):Promise<any> {
    // Parameters obj-

    let params:URLSearchParams = new URLSearchParams();
    let headersvar = new Headers();

    params.set('username', login.userId.toString());
    params.set('password', login.password.toString());
    params.set('grant_type', 'password');
    params.set('scope', 'read write');
    params.set('client_secret', '123456');
    params.set('client_id', 'prithivi');
    var authdata = 'Basic ' + btoa('clientapp' + ':' + '412589');

    headersvar.append('accept', 'application/json');
    headersvar.append('Authorization', authdata);

    let requestOption:RequestOptionsArgs = {
        search: params,
        headers: headersvar,
        body: JSON.stringify({clientapp: 412589})
    };


    return this.http
        .post(OauthUrl, JSON.stringify({clientapp: 412589}), requestOption)
        .toPromise()
        .then(this.extractData)
}

在 Web 服务中添加 CORS 过滤器方法以解决 CORS 问题。下面的代码是 JAVA

 @Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT,DELETE");
        response.setHeader("Access-Control-Max-Age", "3628800");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With, X-XSRF-TOKEN");
        if (!"OPTIONS".equals(request.getMethod())) {
            chain.doFilter(req, res);
        } else {
            response.setStatus(200);
        }
}

【讨论】:

  • 谢谢。我将在哪里覆盖 doFIlter?在我的休息控制器中?
  • 创建一个新类并使用 javax.servlet.filter 接口实现它。
  • 所以我可以在任何有请求映射的类中实现过滤器?
  • 过滤器类将在服务任何请求之前执行,因此最好为过滤器创建一个单独的类
  • 您现在面临的问题是什么?
【解决方案2】:

Prithivi Raj 帮助解决了我的问题,但它并不完整。 我用了他的代码

@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;
        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT,DELETE");
        response.setHeader("Access-Control-Max-Age", "3628800");
        response.setHeader("Access-Control-Allow-Headers", "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With, X-XSRF-TOKEN");
        if (!"OPTIONS".equals(request.getMethod())) {
            chain.doFilter(req, res);
        } else {
            response.setStatus(200);
        }
}

您必须创建一个实现过滤器的过滤器,然后在您的 Web XML 中添加

<filter>
     <filter-name>FilterName</filter-name>
        <filter-class>FilterPackage.FilterClass</filter-class>
</filter>
<filter-mapping>
    <filter-name>FilterName</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

最后,我假设正在使用基本的安全配置,因此在您的 WebSecurityConfigurerAdapter 中,您的配置方法应该类似于下面的代码。基本上你在 BasicAuthenticationFilter 被激活之前添加一个过滤器来解决这个问题。如果您不这样做并且您的登录页面使用身份验证,那么您的过滤器将仅在身份验证后被调用,此时为时已晚

 @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.addFilterBefore(new CorsFilter(), BasicAuthenticationFilter.class);
        http
                .authorizeRequests()
                .antMatchers("/api/login/try").access("hasRole('ROLE_USER')")
                .antMatchers("/api/vehicles/manage/update").access("hasRole('ROLE_USER')")
                .antMatchers("/api/vehicles/manage/create").access("hasRole('ROLE_USER')")
                .antMatchers("/api/proposals/create").access("hasRole('ROLE_USER')")
                .antMatchers("/api/proposals/cancel").access("hasRole('ROLE_USER')")
                .antMatchers("/api/proposals/update").access("hasRole('ROLE_USER')")
                .antMatchers("/api/proposals/accept").access("hasRole('ROLE_USER')")
                .antMatchers("/api/upload").access("hasRole('ROLE_USER')")
                .anyRequest().permitAll()
                .and()
                .csrf().disable()
                .httpBasic()
                .and()
                .logout()
                .permitAll();

    }

感谢 Prithivi Raj 的帮助!

【讨论】:

    猜你喜欢
    • 2018-11-01
    • 2021-12-15
    • 2018-04-01
    • 2021-05-11
    • 2018-10-12
    • 2016-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多