我一直在尝试保护一个应用程序,该应用程序使用注释而不是部署描述符部署到glassfish 3。但是,我无法让它正常工作。如果我尝试访问该服务,我最终会收到服务器错误500,显示以下消息:
type Exception report
message
descriptionThe server encountered an internal error () that prevented it from fulfilling this request.
exception
javax.servlet.ServletException: javax.ejb.AccessLocalException: Client not authorized for this invocation
root cause
javax.ejb.AccessLocalException: Client not authorized for this invocation
EJB看起来像这样:
@Path("/myresource")
@Stateless
@RolesAllowed("user-role")
public class MyResource {
@GET
@Path("/{uuid}")
public Response getData(@PathParam("uuid") final String uuid) {
....
}
}
sun-web.xml中:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD GlassFish Application Server 3.0 Servlet 3.0//EN"
"http://www.sun.com/software/appserver/dtds/sun-web-app_3_0-0.dtd">
<sun-web-app>
<security-role-mapping>
<role-name>user-role</role-name>
<group-name>user-group</group-name>
</security-role-mapping>
</sun-web-app>
这是web.xml:
<web-app id="myservice" version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>org.test.myservice</display-name>
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>org.test.myservice.rest</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Jersey Web Application</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>file</realm-name>
</login-config>
<security-role>
<role-name>user-role</role-name>
</security-role>
</web-app>
glassfish中的文件域是使用sun-web.xml中指定的用户和角色设置的,并且在通过部署描述符设置应用程序安全性时运行良好。
如果我正确理解了这个文档,如果它们的名称相同,我就不必链接安全角色引用。 http://docs.oracle.com/javaee/5/tutorial/doc/bnbyl.html#bnbyt 我缺少什么想法?
修改 与无法使用注释指定所需信息的问题相关,还有另一个问题,这使我想到了这个问题。也许这会使最初的问题更加清晰: 以上为例,资源/ myresource / *仅适用于角色为“user-role”的用户。但是,如果路径/ myresource / * / thumbnail(转换为/ myresource / [uuid] / thumbnail)中有第二个资源(无需身份验证即可使用),则无法通过url-mapping指定security-constraints,因为似乎不可能在常量之间使用通配符。但是,通过指定允许通过注释访问方法的角色,这是可行的。如上所述,我无法这样做。怎么可以做这样的映射?
答案 0 :(得分:2)
您需要使用web.xml描述符中的security-constraint元素来阻止特定资源和路径,并指定授权约束。
这并不意味着您无法使用Programmatic Security添加更细粒度的控件,如Oracle's Java EE 6 Tutorial中所述:
程序化安全性嵌入在应用程序中,用于做出安全决策。当声明性安全性不足以表达应用程序的安全模型时,编程安全性很有用。
根据已修改的问题。
我会使用security-constraint
元素来阻止对所有未注册用户的访问。这将强制每个人进行身份验证,以便您的应用程序知道他们拥有的角色。
然后,您可以使用程序化安全性精细控制对各种资源的访问。
使用基本身份验证,我猜没有其他方法。如果要避免对基本用户进行身份验证,则需要使用表单身份验证并在后台以编程方式处理身份验证,即使他们不知道也可以使用HttpServletRequest#login()对其进行身份验证。
在这两种方式中,您都应该能够以您描述的方式设置权限。如果您想更顺利地处理未经授权的异常,最好删除@RolesAllowed
注释,而是使用以下内容:
@GET
@Path("/{uuid}")
public Response getData(@PathParam("uuid") final String uuid, @Context SecurityContext sc) {
if (sc.isUserInRole("MyRole")) {
return result;
} else {
return notAllowedResult;
}
}
答案 1 :(得分:2)
Roles-Allowed是一个EJB构造,与访问资源不一致,由资源安全约束处理。
不幸的是,这两个安全概念并不像它们应该那样进行网格划分,如果你没有获得授权(网络概念),而不是获得401,你会得到你正在接收的安全性异常(以及EJB概念) 。实际上,如果您使用RolesAllowed注释EJB Web服务并尝试访问具有无效角色的Web服务,我不知道您将收到什么错误。在这种情况下,我假设你会遇到SOAP错误。
EJB安全性是一个保护未经授权的人员的系统,但这是最后的努力。它假设任何将人员路由到方法调用的决定都已经预先完成。例如,没有高级方法来测试是否允许某个方法,而是只能调用它并捕获异常。
因此,严酷的事实超出了粗略的守门人,你想要利用程序化安全性。