将CORS标头添加到j_security_check的响应中

时间:2016-02-05 06:49:30

标签: java-ee cors wildfly j-security-check

我正在使用jax-rs和 WildFly 10 构建 REST API 。一些端点是安全的。我使用基于 FORM 的身份验证。

在我的javascript代码中,我检查AJAX请求的响应,如果它设置为401 Unauthorized,我会向用户显示一个登录表单。当他填写时,我将详细信息发布到j_security_check

localhost上运行一切正常,但当网络服务器和REST服务器在不同的机器上时,浏览器会因跨域问题而拒绝AJAX请求。

我理解CORS,所以我在我的REST服务器中添加了一个CORS过滤器,为GUI服务器设置CORS头。除了一个小而重要的细节外,一切正常:在登录成功后,CORS过滤器不会触发j_security_check响应。没有添加CORS标头,浏览器无法读取响应。

除了这一个细节之外,我整个设置的工作方式与我想要的完全一样....但是我整晚都在努力解决这个问题,而我却无法让它发挥作用。

我理解尝试过滤j_security_check时存在问题,但我知道没有其他方法可以添加CORS标头...所以我的问题是:

如何将CORS标头添加到j_security_check的响应中?

3 个答案:

答案 0 :(得分:4)

undertow / standalone.xml文件中配置domain.xml子系统为我解决了这个问题。在那里配置的过滤器处理所有请求,包括j_security_check一个。

<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>

当然,你最好用"*"标题值属性中的GUI服务器的url替换Access-Control-Allow-Origin通配符。

答案 1 :(得分:1)

自行处理登录

而不是发布到j_security_check,发布到/auth/login或类似的东西并处理登录。像这样:

@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();
    }
}

答案 2 :(得分:0)

基于nfedorovanswer,我得出结论他是对的,并且Undertow过滤器是唯一可以对容器响应进行操作的过滤器类型。因此,如果我们想要为这些响应添加CORS标头,我们需要一个Undertow过滤器。所以我写了一篇:

undertow-cors-filter

下载.zip文件并将其解压缩到Wildfly根文件夹中。然后将filter配置添加到standalone.xml

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

  </filter>
</filters>

filter-ref添加到host元素(仍在standalone.xml中):

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

这将添加CORS标头,允许所有来源访问此服务器发出的所有响应。

param添加到filter定义以配置行为。例如,如果您希望过滤器仅应用于以/api开头的URLS请求的响应,并且您只想允许example.com和example.org访问,则可以使用类似于此的配置:

<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>

有3个策略类可用,AllowAllAllowMatchingWhitelist,您可以根据需要编写自己的自定义策略。