Add CORS headers to response of j_security_check

眉间皱痕 提交于 2020-01-13 05:01:07

问题


I'm building a REST API with jax-rs and WildFly 10. Some of the endpoints are secured. I'm using FORM based authentication.

In my javascript code, I check the response of the AJAX request, and if it is set to 401 Unauthorized, I then present a login form to the user. When he fills it in, I POST the details to j_security_check.

Running on localhost this all works fine, but when the webserver and the REST server are on different machines, the browser denies the AJAX request due to cross-origin issues.

I understand CORS, so I added a CORS filter to my REST server that sets CORS headers for the GUI server. It all works fine, except for one small, but important detail: after the login has succeeded, the CORS filter does not fire for the j_security_check response. No CORS headers are added and the browser can not read the response.

Apart from this one detail I have the whole setup working exactly like I want it.... But I have been struggling with this detail all night and I just can't get it to work.

I understand there are issues with trying to filter j_security_check, but I know of no other ways to add CORS headers... So my question is:

How do I add CORS headers to the response for j_security_check?


回答1:


Configuring undertow subsystem in standalone.xml/domain.xml file solved this problem for me. Filters configured there handle all the requests including j_security_check one.

<subsystem xmlns="urn:jboss:domain:undertow:3.0">
            <buffer-cache name="default"/>
            <server name="default-server">
                <http-listener name="default" redirect-socket="https" socket-binding="http"/>
                <host name="default-host" alias="localhost">
                    <location name="/" handler="welcome-content"/>
                    <filter-ref name="server-header"/>
                    <filter-ref name="x-powered-by-header"/>
                    <!--CORS headers -->
                    <filter-ref name="Access-Control-Allow-Origin"/>
                    <filter-ref name="Access-Control-Allow-Methods"/>
                    <filter-ref name="Access-Control-Allow-Headers"/>
                    <filter-ref name="Access-Control-Allow-Credentials"/>
                    <filter-ref name="Access-Control-Max-Age"/>
                </host>
            </server>
            <servlet-container name="default">
                <jsp-config/>
                <websockets/>
            </servlet-container>
            <handlers>
                <file name="welcome-content" path="${jboss.home.dir}/welcome-content"/>
            </handlers>
            <filters>
                <response-header name="server-header" header-value="WildFly/10" header-name="Server"/>
                <response-header name="x-powered-by-header" header-value="Undertow/1" header-name="X-Powered-By"/>
                <!-- CORS headers -->
                <response-header name="Access-Control-Allow-Origin" header-name="Access-Control-Allow-Origin" header-value="*"/>
                <response-header name="Access-Control-Allow-Methods" header-name="Access-Control-Allow-Methods" header-value="OPTIONS, GET, POST, PUT, DELETE"/>
                <response-header name="Access-Control-Allow-Headers" header-name="Access-Control-Allow-Headers" header-value="accept, authorization, content-type, x-requested-with"/>
                <response-header name="Access-Control-Allow-Credentials" header-name="Access-Control-Allow-Credentials" header-value="true"/>
                <response-header name="Access-Control-Max-Age" header-name="Access-Control-Max-Age" header-value="60"/>
            </filters>
        </subsystem>

Of course you'd better replace "*" wildcard by your GUI server's url in the Access-Control-Allow-Origin header's value attribute.




回答2:


Handle the login yourself.

Instead of posting to j_security_check, post to /auth/login or something like that and handle the login. Something like this:

@POST
@Path("login")
@PermitAll
public Response postLogin() {
    String user = request.getParameter("j_username");
    String password = request.getParameter("j_password");
    StringBuffer buf = request.getRequestURL();
    URI redir = null; 
    try {redir = new URI(buf.substring(0, buf.lastIndexOf("/login")) + "/session");} 
    catch (URISyntaxException e) {}
    try {
        request.login(user, password);
        return Response.seeOther(redir).build();
    } catch (ServletException e) {
        if (e.getMessage() != null && e.getMessage().equals("UT010030: User already logged in")) {
            Response.seeOther(redir).build();
        }
        return Response.status(Status.FORBIDDEN).build();
    }
}



回答3:


Based on nfedorov's answer, I came to the conclusion that he is right and that an Undertow filter is the only type of filter that can operate on container responses. So if we want to add CORS headers to these responses, we need an Undertow filter. So I wrote one:

undertow-cors-filter

Download the .zip file and unzip it in your Wildfly root folder. Then add a filter configuration to standalone.xml:

<filters>
  <filter name="undertow-cors-filter" class-name="com.stijndewitt.undertow.cors.Filter" module="com.stijndewitt.undertow.cors">

  </filter>
</filters>

Add a filter-ref to the host element (still in standalone.xml):

<host name="default-host" alias="localhost">
  <filter-ref name="undertow-cors-filter" />
</host>

This will add CORS headers allowing all origins access to all responses this server emits.

Add params to the filter definition to configure the behavior. For example, if you want the filter to apply only to responses for requests to URLS starting with /api and you only want to allow example.com and example.org access, you could use a configuration similar to this:

<filters>
  <filter name="undertow-cors-filter" class-name="com.stijndewitt.undertow.cors.Filter" module="com.stijndewitt.undertow.cors">
    <param name="urlPattern" value="^http(s)?://([^/]+)(:([^/]+))?(/([^/])+)?/api(/.*)?$" />
    <param name="policyClass" value="com.stijndewitt.undertow.cors.AllowMatching" />
    <param name="policyParam" value="^http(s)?://(www\.)?example\.(com|org)$" />   
  </filter>
</filters>

There are 3 policy classes available, AllowAll, AllowMatching and Whitelist and you can write your own custom policies if needed.



来源:https://stackoverflow.com/questions/35217936/add-cors-headers-to-response-of-j-security-check

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!