如何将401响应的内容更改为单个格式?

时间:2017-04-04 12:53:14

标签: jax-rs http-status-code-401 custom-error-pages

我在WildFly 10上有一个JAX-RS应用程序,它应该由一个简单的Basic Auth保护。

它到目前为止有效,但如果身份验证失败,服务器将以

响应
<html>
  <head>
    <title>Error</title>
  </head>
  <body>Unauthorized</body>
</html>

这不是我想要的回应。我更喜欢定制(json)响应。

怎么做?

到目前为止我做了什么:

  1. 我在服务器配置中使用一个简单的UserRolesLoginModule配置了一个新的Wildfly安全域(在我的情况下就足够了):

    <security-domain name="MySecurityDomain" cache-type="default">
      <authentication>
        <login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required">
          <module-option name="usersProperties" value="${jboss.server.config.dir}/users.properties"/>
          <module-option name="rolesProperties" value="${jboss.server.config.dir}/roles.properties"/>                            
          <module-option name="hashAlgorithm" value="MD5"/>
          <module-option name="hashEncoding" value="base64"/>
          <module-option name="hashCharset" value="UTF-8"/>
          <module-option name="unauthenticatedIdentity" value="UnauthenticatedAccess"/> 
        </login-module>                                       
      </authentication>
    </security-domain>
    
  2. 我在应用中注释了所有服务:

         @SecurityDomain("MySecurityDomain")
         @RolesAllowed({ "RoleFromPropertyFile", "AnotherRoleFromPropertyFile" })
    
  3. 我用内容

    创建了一个jboss-web.xml
        <jboss-web>
          <security-domain>MySecurityDomain</security-domain>
        </jboss-web>
    
  4. 我有一个web.xml,在那里我尝试了很多不同的东西而没有任何成功...... :-(
    目前的内容:

        <security-constraint>
          <display-name>Deny all HTTP methods except GET and POST</display-name>
          <web-resource-collection>
            <web-resource-name>NextTest</web-resource-name>
            <url-pattern>/mypattern/*</url-pattern>
            <http-method-omission>GET</http-method-omission>
            <http-method-omission>POST</http-method-omission>
         </web-resource-collection>    
       </security-constraint>
       <login-config>
         <auth-method>BASIC</auth-method>
         <realm-name>MySecurityRealm</realm-name>
       </login-config>
      <security-role>
         <description>Access to all application parts</description>
         <role-name>all</role-name>
     </security-role>    
     <!-- and some more roles -->
    
  5. 我还实现了ExceptionMapper<EJBAccessException>来生成我自己的回复。但是,当我删除web.xml的所有内容时,才会触及此映射器。

  6. 我的猜测是,承诺正在进行授权并处理未经授权访问的响应。如果我删除web.xml中的安全配置,则会访问EJB,但不会评估BasicAuth标头。在这种情况下,所有请求都被拒绝。

    我可能会避免编写Servlet并改为使用ExceptionMapper。

    我错过了哪些想法?

2 个答案:

答案 0 :(得分:0)

我做了一些代码的实验,虽然它不漂亮,你可以尝试类似的东西:

import java.io.IOException;

import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.ext.Provider;

@Provider
public class AuthBodyResponseFilter implements ContainerResponseFilter {

    @Override
    public void filter(ContainerRequestContext requestContext,
                       ContainerResponseContext responseContext) throws IOException {

        if((responseContext.getStatus() == 401) && 
           (responseContext.getEntity() instanceof String))
            responseContext.setEntity("no services for you!");
    }
}

我测试了一下它似乎工作。当然,挑战在于其他地方有一个带有String响应体的401吗?我必须测试更多,看看这是否涵盖了所有内容。

答案 1 :(得分:0)

我是这样做的:

@POST
@Consumes("application/json")
@Produces("application/json")
public Response create(Entity entity) {
    try {
        Entity created = service().create(entity);
        return Response.created(location(created)).entity(created).build();
    } catch (ServiceException e) {
        return Response.status(e.getStatus()).entity(e).build();
    }
}

请注意返回类型Response。这允许您自定义响应,包括设置标题等。这也意味着您必须编写更多的接线代码。

我在这里使用已经拥有状态的自定义ServiceException并使用它来设置响应代码。然后我传递异常本身,它将作为JSON返回。