无法设置认证头有角和春季安全 [英] Can't set Authentication Header with Angular and Spring Security

查看:133
本文介绍了无法设置认证头有角和春季安全的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了麻烦角,CORS,SpringSecurity和基本身份验证,以发挥很好。我有以下的角Ajax调用在这里我想设置页眉包括在请求中的基本授权头。

I'm having trouble getting Angular, CORS, SpringSecurity and Basic Authentication to play nicely. I have the following Angular Ajax call where I'm trying to set the header to include a Basic Authorization header in the request.

var headerObj = {headers: {'Authorization': 'Basic am9lOnNlY3JldA=='}};
return $http.get('http://localhost:8080/mysite/login', headerObj).then(function (response) {
    return response.data;
});

我正在我的本地主机上的应用程序的角度:8888和本地主机上我的后台服务器:8080。所以我不得不一个CORS筛选器添加到我的服务器端是Spring MVC的。所以,我创建了一个过滤器,并把它添加到我的web.xml。

I am running my angular app on localhost:8888 and my backend server on localhost:8080. So I had to add a CORS filter to my server side which is Spring MVC. So I created a filter and added it to my web.xml.

的web.xml

<filter>
    <filter-name>corsFilter</filter-name>
    <filter-class>com.abcinsights.controller.SimpleCorsFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>corsFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

CorsFilter

CorsFilter

public class SimpleCorsFilter extends OncePerRequestFilter {

@Override
public void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {
    Enumeration<String> headerNames = req.getHeaderNames();
    while(headerNames.hasMoreElements()){
        String headerName = headerNames.nextElement();
        System.out.println("headerName " + headerName);
        System.out.println("headerVal " + req.getHeader(headerName));
    }               
    HttpServletResponse response = (HttpServletResponse) res;
    response.setHeader("Access-Control-Allow-Origin", "*"); 
    response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
    response.setHeader("Access-Control-Max-Age", "3600");
    response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Range, Content-Disposition, Content-Type, Authorization");
    chain.doFilter(req, res);
}   
}

这一切工作正常,当我看标题名称/值,我看到我的基本价值和硬codeD Base64编码字符串Authorization头。

This all works fine and when I look at the header names/values I see my Authorization header with the Basic value and the hard coded Base64 string.

于是我尝试添加SpringSecurity它将使用认证头做基本身份验证。下面是添加了春季安全我的web.xml和春季安全配置。

So then I tried to add SpringSecurity which would use the Authorization header to do basic authentication. Here's my web.xml and spring security config with Spring Security added in.

更新的web.xml

updated web.xml

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/config/security-config.xml</param-value>
</context-param>

<filter>
  <filter-name>springSecurityFilterChain</filter-name>
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>

<filter-mapping>
  <filter-name>springSecurityFilterChain</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

安全-config.xml中

security-config.xml

<http auto-config="true" use-expressions="false">
    <intercept-url pattern="/**" access="ROLE_USER" />
    <http-basic/>
    <custom-filter ref="corsHandler" before="SECURITY_CONTEXT_FILTER"/>
</http>

<beans:bean id="corsHandler" class="com.abcinsights.controller.SimpleCorsFilter"/>

<authentication-manager>
    <authentication-provider>
        <jdbc-user-service data-source-ref="dataSource"/>
    </authentication-provider>
</authentication-manager>

正如你所看到的,我不得不添加我CORS筛选到春季安全过滤器链的前端(我也是从web.xml中删除它)。这似乎在这个意义上是工作,当我提出请求的CORS过滤器仍然被调用。但是从我的AJAX调用来不再要求有中添加的Authorization头。当我删除SpringSecurity过滤器链,只是把我的CORS筛选回到web.xml中的Authorization头回来。我在一个损失,但我想知道如果它是与preflight通信工作的一种方式,当我CORS过滤器在web.xml中独立而另一种方式,当它在春季安全过滤器链?任何帮助将是AP preciated。

As you can see, I had to add my CORS filter to the front of the spring security filter chain (I also removed it from web.xml). This seems to be working in the sense that the CORS filter still gets called when I make a request. But the request coming from my AJAX call no longer has the Authorization header added in. When I remove the SpringSecurity filter chain and just put my CORS filter back into web.xml the Authorization header comes back. I'm at a loss but am wondering if it has something to do with preflight communication working one way when my CORS filter is stand alone in web.xml and another way when it is in the Spring Security filter chain? Any help would be appreciated.

感谢

推荐答案

但问题是,角是发送一个HTTP OPTIONS没有HTTP Authorization头要求。那么Spring安全受到处理该请求,并发送回一个401未授权的响应。所以我的角度应用渐渐从春天401响应上的选项要求,而不是一个200响应告诉角度先走,并发送也有Authorization头在它的POST请求。因此,修复是

The problem was that angular was sending an HTTP OPTIONS request without the HTTP Authorization header. Spring security was then processing that request and sending back a 401 Unauthorized response. So my angular app was getting a 401 response from spring on the OPTIONS request rather than a 200 response telling angular to go ahead and send the POST request that did have the Authorization header in it. So the fix was to

一)把我CORSFilter并在web.xml中我SpringSecurity过滤器(而不是我在Spring从名为CORS过滤器)。不是100%肯定这使得有差别,但,这就是我最后的web.xml样子。

a) Put my CORSFilter and my SpringSecurity filter in web.xml (rather than having my CORS Filter called from within Spring). Not 100% sure this made a difference but that's what my final web.xml looked like.

二)增加从下面的链接code到我的CORS筛选,以便它不委托给SpringSecurity为OPTIONS请求类型。

b) Added the code from the below link to my CORS Filter so that it doesn't delegate to SpringSecurity for OPTIONS request types.

这个职位是什么让我整理出:<一href=\"http://stackoverflow.com/questions/30632200/standalone-spring-oauth2-jwt-authorization-server-cors/30638914#30638914\">Standalone春天的OAuth2智威汤逊授权服务器+ CORS

This post was what got me sorted out: Standalone Spring OAuth2 JWT Authorization Server + CORS

下面是我的code:

的web.xml

<display-name>ABC Insights</display-name>
<servlet>
    <servlet-name>abcInsightsServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/config/servlet-config.xml</param-value>
    </init-param> 
</servlet>
<servlet-mapping>
    <servlet-name>abcInsightsServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<!--  Stand Alone Cross Origin Resource Sharing Authorization Configuration -->
<filter>
    <filter-name>corsFilter</filter-name>
    <filter-class>com.abcinsights.controller.SimpleCorsFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>corsFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>       
<!--  Spring Security Configuration -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/config/security-config.xml</param-value>
</context-param>    
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

下面是我的CORS筛选:

Here is my CORS Filter:

public class SimpleCorsFilter extends GenericFilterBean {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;       
        response.setHeader("Access-Control-Allow-Origin", "*"); 
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Range, Content-Disposition, Content-Type, Authorization, X-CSRF-TOKEN");  

        if ("OPTIONS".equalsIgnoreCase(request.getMethod())) {
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            chain.doFilter(req, res);
        }           
    }
}

下面是我的角code:

Here is my Angular code:

var login = function (credentials) {
    console.log("credentials.email: " + credentials.email);
    console.log("credentials.password: " + credentials.password);

    var base64Credentials = Base64.encode(credentials.email + ':' + credentials.password);

    var req = {
        method: 'GET',
        url: 'http://localhost:8080/abcinsights/loginPage',
        headers: {
            'Authorization': 'Basic ' + base64Credentials
        }
    }

    return $http(req).then(function (response) {
        return response.data;
    });        
};

希望有所帮助。

这篇关于无法设置认证头有角和春季安全的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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