我在WildFly 10上有一个JAX-RS应用程序,它应该由一个简单的Basic Auth保护。
它到目前为止有效,但如果身份验证失败,服务器将以
响应<html>
<head>
<title>Error</title>
</head>
<body>Unauthorized</body>
</html>
这不是我想要的回应。我更喜欢定制(json)响应。
怎么做?
到目前为止我做了什么:
我在服务器配置中使用一个简单的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>
我在应用中注释了所有服务:
@SecurityDomain("MySecurityDomain")
@RolesAllowed({ "RoleFromPropertyFile", "AnotherRoleFromPropertyFile" })
我用内容
创建了一个jboss-web.xml <jboss-web>
<security-domain>MySecurityDomain</security-domain>
</jboss-web>
我有一个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 -->
我还实现了ExceptionMapper<EJBAccessException>
来生成我自己的回复。但是,当我删除web.xml
的所有内容时,才会触及此映射器。
我的猜测是,承诺正在进行授权并处理未经授权访问的响应。如果我删除web.xml
中的安全配置,则会访问EJB,但不会评估BasicAuth标头。在这种情况下,所有请求都被拒绝。
我可能会避免编写Servlet并改为使用ExceptionMapper。
我错过了哪些想法?
答案 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返回。