NULL http标头从Angular2应用程序传递到服务器 [英] NULL http headers are passed to the server from Angular2 app

查看:146
本文介绍了NULL http标头从Angular2应用程序传递到服务器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用SpringBoot开发的REST api,它包含用于身份验证和授权的JWT实现。使用 FilterRegistrationBean

I have a REST api developed using SpringBoot and it contains the implementation for JWT for authentication and authorization. A FilterRegistrationBean is used for that.

我有一个名为 JwtFilter 的类,它扩展了 GenericFilterBean 。在那里,我查找请求标头的内容,以便授权用户。

I have a class called JwtFilter which extends GenericFilterBean. In that I look for the content of the request headers in order to authorize the users.

public class JwtFilter extends GenericFilterBean{

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

        System.out.println("INSIDE JWT FILTER");

        final HttpServletRequest request = (HttpServletRequest) req;

        final String authHeader = request.getHeader("Authorization");
        String reqHdr = request.getHeader("X-Requested-By");
        String myHdr = request.getHeader("myheader");

        System.out.println("Auth header = "+authHeader);
        System.out.println("requested by header = "+reqHdr);
        System.out.println("my header = "+myHdr);


        if (authHeader == null || !authHeader.startsWith("Bearer ")) {
            System.out.println("JwtFilter.doFilter -> auth header is null or token does not start with Bearer");
            throw new ServletException("Missing or invalid Authorization header.");
        }

        final String token = authHeader.substring(7); // The part after "Bearer "

        try {
            final Claims claims = Jwts.parser().setSigningKey("secretkey").parseClaimsJws(token).getBody();
            request.setAttribute("claims", claims);
        }
        catch (final SignatureException e) {
            System.out.println("VIRGLK EXCEPTION : JwtFilter.doFilter -> Signature Exception, invalid token = "+e.getMessage());
            throw new ServletException("Invalid token.");
        }

        chain.doFilter(req, res);
    }

}

我可以保证设置标题动态工作正常,因为我测试了一些其他HTTP请求到同一台服务器,而不是url过滤(登录请求)。

I can assure that setting the headers dynamically works fine, since I tested it for some other HTTP requests to the same server which are not url filtered(login request).

但是,当涉及到上面类过滤的请求时,我看到请求的每个头都为空。

But, when it comes to the requests which are filtered by above class, I see that every header of the requests are null.

以下是我如何在Angular2中的请求中添加标题。我扩展了 BaserequestOptions 类并重写了merge方法,以便动态添加标头。

Given below is how I add headers in to the requests in Angular2. I have extended BaserequestOptions class and overridden the merge method in order to add headers dynamically.

@Injectable()
export class CustomRequestOptions extends BaseRequestOptions {
    constructor(private _globals: Globals) {
        super();
        this.headers.set('Content-Type', 'application/json');
        this.headers.set('X-Requested-By', 'Angular 2');
    }

    merge(options?: RequestOptionsArgs): RequestOptions {
        var newOptions = super.merge(options);
        let hdr = this._globals.getAuthorization();
        newOptions.headers.set("Authorization", hdr);
        newOptions.headers.set("myheader", "my header value");
        return newOptions;
    }

}

但是这些标题在选中时为空在过滤的请求的API中。如上所述,未过滤的请求没有问题。静态附加('X-Requested-By')和动态附加('myheader')标头,并在服务器中可用。

But these headers are null when checked in the API for the requests which are filtered. As I mentioned above, there is no problem for the non filtered requests. Both statically appended('X-Requested-By') and dynamically appended('myheader') headers and available in the server.

我无法理解这里发生了什么。至少,我不知道,从哪一方来说,错误来自于此。

I cannot understand what is happening here. At least, I have no clue, from which side, the error is coming from.

以下是从浏览器控制台为失败的请求复制的请求标头。

Following is the request header copied from browser console for the failed request.

OPTIONS /protected/get-roles/USER HTTP/1.1
Host: 127.0.0.1:8080
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: http://localhost:3000
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
Access-Control-Request-Headers: authorization,content-type,myheader,x-requested-by
Accept: */*

有人能指出我这里可能存在的问题。我很无能为力。

Can someone point me out what could be the issue here. I am clueless.

编辑

我想这个问题来自服务器因为以下原因。

I guess the issue is coming from the server because of the following reason.

我能够成功检索请求的所有标头值,这是在设置了授权标头并且该请求不是已过滤的请求之后完成的。因此我想,JWT过滤器实现有问题。

I was able to successfully retrieve all the header values of a request which was done after the authorization header is set and that request is not a filtered one. Therefore I guess, there is something wrong with the JWT Filter implementation.

这可能是一个愚蠢的问题,但是,是否由于我发送的请求的原因是不在类型的ServletRequest 可能是? doFilter 中的方法JwtFilter 接受 ServletRequest 的参数。

This might be a stupid question, but, Is it due to the reason that the requests I send are not in the type of ServletRequest may be? doFilter method in JwtFilter accepts the parameter of ServletRequest.

推荐答案

我想写一个我在这里找到答案的解决方案,因为它可能会对将来有所帮助。感谢JB Nizet的评论。他向我展示了问题所在。

I thought of writing the solution I found as an answer here since it might help someone in future. Thanks goes to JB Nizet for his comment. He showed me where the issue is.

这是CORS的一个问题。在发送实际GET请求(在我的情况下)之前,浏览器发送了一个飞行前请求。正如@JB Nizet指出的那样,我改变了我的代码,参考了以下链接的答案。

It was an issue with CORS. A pre-flight request was there sent by the browser before the actual GET request(in my case) was sent. As @JB Nizet pointed out, I changed my code referring the following linked answers.

使用Spring Security进行跨域资源共享

响应中的头部不能是通配符'* '当请求的凭据模式为'包含'

我的 JwtFilter 现在看起来像这样

public class JwtFilter extends GenericFilterBean{

    private final List<String> allowedOrigins = Arrays.asList("http://localhost:3000");

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

        System.out.println("INSIDE JWT FILTER");

        final HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;


        // Access-Control-Allow-Origin
        String origin = request.getHeader("Origin");
        response.setHeader("Access-Control-Allow-Origin", allowedOrigins.contains(origin) ? origin : "");
        response.setHeader("Vary", "Origin");

        // Access-Control-Max-Age
        response.setHeader("Access-Control-Max-Age", "3600");

        // Access-Control-Allow-Credentials
        response.setHeader("Access-Control-Allow-Credentials", "true");

        // Access-Control-Allow-Methods
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");

        // Access-Control-Allow-Headers
        response.setHeader("Access-Control-Allow-Headers",
                "Origin, Authorization, myheader, X-Requested-By, X-Requested-With, Content-Type, Accept, " + "X-CSRF-TOKEN");

        if (request.getMethod().equals("OPTIONS")) {
            response.flushBuffer();
        }else{

            final String authHeader = request.getHeader("Authorization");
            String reqHdr = request.getHeader("X-Requested-By");
            String myHdr = request.getHeader("myheader");

            System.out.println("=====================================================");
            System.out.println("Auth header = "+authHeader);
            System.out.println("requested by header = "+reqHdr);
            System.out.println("my header = "+myHdr);
            System.out.println("=====================================================");

            if (authHeader == null || !authHeader.startsWith("Bearer ")) {
                System.out.println("JwtFilter.doFilter -> auth header is null or token does not start with Bearer");
                throw new ServletException("Missing or invalid Authorization header.");
            }

            final String token = authHeader.substring(7); // The part after "Bearer "

            try {
                final Claims claims = Jwts.parser().setSigningKey("secretkey").parseClaimsJws(token).getBody();
                request.setAttribute("claims", claims);
            }
            catch (final SignatureException e) {
                System.out.println("JwtFilter.doFilter -> Signature Exception, invalid token = "+e.getMessage());
                throw new ServletException("Invalid token.");
            }

            chain.doFilter(req, res);

        }


    }

}

快乐编码!

这篇关于NULL http标头从Angular2应用程序传递到服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆