AngularJS、Spring Social 和 CORS

Posted

技术标签:

【中文标题】AngularJS、Spring Social 和 CORS【英文标题】:AngularJS, Spring Social and CORS 【发布时间】:2015-05-12 07:17:45 【问题描述】:

我有一个使用 Spring 和 Spring Social 构建的应用程序。

我能够连接到社交网络,效果很好。然后我有了一个好主意,在前端使用 Angular 而不是 jsp,并着手将我用来连接社交网络的 html 表单替换为使用 angular 的 http 帖子。

现在我得到了错误

XMLHttpRequest cannot load https://accounts.google.com/o/oauth2/auth?client_id=233119510011-epdnrh651t…%2Fconnect%2Fgoogle&scope=email&state=e29561c9-a538-47dd-8b92-ca0aaa8b413b. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8080' is therefore not allowed access. 

表单帖子有效,但 angularjs 帖子无效。是什么赋予了?我使用 fidler 查看了失败的 Angular 帖子,将其与工作的 html 表单帖子进行了比较,发现了这一点。

使用 html 表单工作 POST

 POST http://localhost:8080/connect/google HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 54
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.76 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: http://localhost:8080/myscene/account-settings
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8
Cookie: _ga=GA1.1.679586999.1424266167; JSESSIONID=74A29A5F0B04B937281A7FAC4DD7B102
X-Forwarded-For: 12.13.14.15

_csrf=c71a3881-d272-42de-b8b1-c7647f7e7609&scope=email

这是发布该帖子的代码

<form action='<c:url value="/connect/google" />' method="POST">
                        <input name="$_csrf.parameterName"
                            value="$_csrf.token" /> <input name="scope"
                            value="email" />
                        <button type="submit" class="common_button">Connect with
                            Google</button>
                    </form>

使用 angularjs 不起作用的 POST

POST http://localhost:8080/connect/google HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Content-Length: 54
Origin: http://localhost:8080
X-XSRF-TOKEN: c71a3881-d272-42de-b8b1-c7647f7e7609
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.76 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Cache-Control: max-age=0
Referer: http://localhost:8080/myscene/account-settings
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.8
Cookie: _ga=GA1.1.679586999.1424266167; JSESSIONID=74A29A5F0B04B937281A7FAC4DD7B102
X-Forwarded-For: 12.13.14.15

_csrf=c71a3881-d272-42de-b8b1-c7647f7e7609&scope=email

这是发布该帖子的代码

$http(
                  method  : 'POST',
                  url     : '/connect/google',
                  data    : $.param(oauth2Scope),  // pass in data as strings
                  headers :  
                                'Content-Type': 'application/x-www-form-urlencoded',
                                'X-XSRF-TOKEN'   : token,
                                'Cache-Control'  : 'max-age=0',
                                'Accept'         : 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
                              
                 )

我在正确的轨道上吗?我发现这很棘手,所以任何帮助都非常受欢迎!希望有人能指出我正确的方向。

编辑 1:

我已经创建了一个过滤器服务器端,但没有工作,所以我必须做其他事情。

编辑 2:

此外,值得注意的是,产生错误的请求是 Spring Social Framework 对谷歌服务器的 GET。导致问题的我的角度 POST 是 localhost:8080 并由 Spring Social 处理。

编辑 3: 所以我注意到只有当 spring social 将 GET 发送到 google / facebook 而不是我自己的网站时,这才是一个问题。对于我自己的网站,我可以使用 Angular Fine 提交 ajax 帖子。

另外,我注意到谷歌的非工作 GET 包含 Origin,而谷歌的工作 GET 则没有。这可能是问题吗?

过滤器

@Component
public class SimpleCORSFilter implements Filter 

    @Override
    public void init(FilterConfig filterConfig) throws ServletException 
        // TODO Auto-generated method stub

    

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

        HttpServletResponse response = (HttpServletResponse) resp;

        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", "x-requested-with");

        chain.doFilter(req, resp);
    

    @Override
    public void destroy() 
    


【问题讨论】:

【参考方案1】:

您的 servlets/rest 服务必须设置 CORS 标头,我注意到 $http 在调用之前会检查 http OPTIONS。

添加此功能的最佳方法是添加标题条目的过滤器。

见Tomcat CORS filter

【讨论】:

谢谢。我曾尝试通过 Spring 添加一个过滤器,因此将其包含在我原来的问题中,以防它出现问题。除此之外,我将研究您提供的链接中的流程图。看起来很棒。

以上是关于AngularJS、Spring Social 和 CORS的主要内容,如果未能解决你的问题,请参考以下文章

spring social facebook + api + angularjs(如何从 angular 调用 -> spring api -> 重定向到 facebook 登录)

Grails - Spring Security / Social - Facebook 插件 setAccessToken 和 getAccessToken

使用 Angularjs 和 Mongoose (meanjs) 创建子文档并保存值

使用 MongoDB 的 Spring Social 和 Spring Security

Spring social 和 oauth2 协议有啥关系?

如何通过 REST API 为 Spring-social 和 spring-security 设置登录服务?