当前位置: 首页 > 知识库问答 >
问题:

与Spring Security的跨源资源共享

蒋高杰
2023-03-14

我试图使CORS与Spring Security很好地配合,但它并不符合要求。我进行了本文所述的更改,更改applicationcontext-security.xml中的这一行使我的应用程序可以使用POST和GET请求(临时公开控制器方法,以便测试CORS):

  • 前面:
  • 后面:

不幸的是,允许通过AJAX进行Spring Security登录的以下URL没有响应:http://localhost:8080/mutopia-server/resources/j_spring_security_check。我正在将AJAX请求从http://localhost:80发送到http://localhost:8080

当尝试访问j_spring_security_check时,我在Chrome中获得了(pending)选项预飞行请求,AJAX调用返回HTTP状态代码0和消息“error”。

在HTTP状态代码302的情况下,预试运行成功,之后我仍然直接获得AJAX请求的错误回调,并且HTTP状态为0和消息“error”。

function get(url, json) {
    var args = {
        type: 'GET',
        url: url,
        // async: false,
        // crossDomain: true,
        xhrFields: {
            withCredentials: false
        },
        success: function(response) {
            console.debug(url, response);
        },
        error: function(xhr) {
            console.error(url, xhr.status, xhr.statusText);
        }
    };
    if (json) {
        args.contentType = 'application/json'
    }
    $.ajax(args);
}

function post(url, json, data, dataEncode) {
    var args = {
        type: 'POST',
        url: url,
        // async: false,
        crossDomain: true,
        xhrFields: {
            withCredentials: false
        },
        beforeSend: function(xhr){
            // This is always added by default
            // Ignoring this prevents preflight - but expects browser to follow 302 location change
            xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
            xhr.setRequestHeader("X-Ajax-call", "true");
        },
        success: function(data, textStatus, xhr) {
            // var location = xhr.getResponseHeader('Location');
            console.error('success', url, xhr.getAllResponseHeaders());
        },
        error: function(xhr) {
            console.error(url, xhr.status, xhr.statusText);
            console.error('fail', url, xhr.getAllResponseHeaders());
        }
    }
    if (json) {
        args.contentType = 'application/json'
    }
    if (typeof data != 'undefined') {
        // Send JSON raw in the body
        args.data = dataEncode ? JSON.stringify(data) : data;
    }
    console.debug('args', args);
    $.ajax(args);
}

var loginJSON = {"j_username": "username", "j_password": "password"};

// Fails
post('http://localhost:8080/mutopia-server/resources/j_spring_security_check', false, loginJSON, false);

// Works
post('http://localhost/mutopia-server/resources/j_spring_security_check', false, loginJSON, false);

// Works
get('http://localhost:8080/mutopia-server/landuses?projectId=6', true);

// Works
post('http://localhost:8080/mutopia-server/params', true, {
    "name": "testing",
    "local": false,
    "generated": false,
    "project": 6
}, true);

请注意-我可以通过CORS发布到我的应用程序中的任何其他URL(Spring Security登录除外)。我读了很多文章,所以对这个奇怪的问题的任何见解都将非常感激

共有1个答案

萧嘉茂
2023-03-14

我可以通过扩展UsernamePasswordAuthenticationFilter...我的代码在Groovy中,希望可以:

public class CorsAwareAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
    static final String ORIGIN = 'Origin'

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response){
        if (request.getHeader(ORIGIN)) {
            String origin = request.getHeader(ORIGIN)
            response.addHeader('Access-Control-Allow-Origin', origin)
            response.addHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE')
            response.addHeader('Access-Control-Allow-Credentials', 'true')
            response.addHeader('Access-Control-Allow-Headers',
                    request.getHeader('Access-Control-Request-Headers'))
        }
        if (request.method == 'OPTIONS') {
            response.writer.print('OK')
            response.writer.flush()
            return
        }
        return super.attemptAuthentication(request, response)
    }
}

上述重要比特:

  • 仅在检测到CORS请求时向响应添加CORS标头
  • 使用简单的非空200响应来响应飞行前选项请求,该响应还包含CORS头。

您需要在Spring配置中声明这个bean。有很多文章显示了如何这样做,所以我不会在这里复制它。

在我自己的实现中,我使用了一个起源域白名单,因为我只允许内部开发人员访问CORS。上面是我正在做的一个简化版本,所以可能需要调整,但这应该给你大致的想法。

 类似资料:
  • 来自维基百科: 要发起跨源请求,浏览器发送带有源HTTP标头的请求。这个标题的值是为页面服务的站点。例如,假设http://www.example-social-network.com上的一个页面试图访问online-personal-calendar.com中的用户数据。如果用户的浏览器实现了CORS,则将发送以下请求头: 来源:http://www.example-social-network

  • 通过XHR 实现Ajax 通信的一个主要限制,来源于跨域安全策略。默认情况下,XHR 对象只能访问与包含它的页面位于同一个域中的资源。这种安全策略可以预防某些恶意行为。但是,实现合理的跨域请求对开发某些浏览器应用程序也是至关重要的。 CORS(Cross-Origin Resource Sharing,跨源资源共享)是W3C 的一个工作草案,定义了在必须访问跨源资源时,浏览器与服务器应该如何沟通。

  • 问题内容: 对于以下ajax发布请求Flask(如何使用烧瓶中ajax发布的数据?): 我收到一个错误: 我尝试通过以下两种方法解决该问题,但似乎没有任何效果。 1.使用Flask-CORS 这是用于处理的扩展,应使跨域AJAX成为可能。 我的pythonServer.py使用此解决方案: 2.使用特定的Flask装饰器 这是Flask 官方代码片段,定义了一个装饰器,该装饰器应允许CORS其装饰

  • 问题内容: 对于以下发布请求如何使用烧瓶中从ajax发布的数据?: 我收到一个错误: 我尝试通过以下两种方式解决该问题,但似乎无济于事。 使用Flask-CORS 这是用于处理的扩展,应使跨域AJAX成为可能。 我的 pythonServer.py 使用此解决方案: 使用特定的Flask装饰器 这是Flask 官方 代码片段,定义了一个装饰器,该装饰器应允许其装饰功能。 http://flask.

  • 对于以下post请求(如何在flask中使用从ajax发布的数据?): 我得到一个错误: null http://flask-cors.readthedocs.org/en/latest/ 如何在烧瓶和Heroku中启用CORS 应用jwt auth包装器时Flask-cors包装器不工作。 JavaScript-请求的资源上没有'access-control-allog-origin'标头 我的

  • 问题内容: 我正在编写一个HTML5应用程序,该应用程序使用JSONP从几个不同的来源收集数据。我对GET所做的任何事情都可以正常工作。我现在正尝试发布数据,并且遇到了一个有趣的问题。我需要将数据从我的应用程序发布到另一个应用程序,该应用程序从本地计算机运行。我正在尝试编写具有跨平台功能的移动应用程序(请考虑使用Pulse / Flipboard),因此该代码将始终从本地源运行。我的思考过程如下: