问题
I am using JAX-RS using jersey implementation. I am trying to authenticate my service using BASIC authentication using Tomcat 6.
This is the code:
@Path("/authenticate")
@RolesAllowed({"Admin","Guest"})
public class BasicAuthenticationSecurity {
@GET
@Path("/wbiPing")
@Produces(MediaType.TEXT_PLAIN)
@RolesAllowed("Admin")
public Response wbiPing(){
System.out.println("Pinged!!!");
return Response.ok("Pinged!!!").build();
}
}
When I try to annotate my method using @RolesAllows, I am getting an compilation error:
@RolesAllows cannot be resolved to a type
Please let me know how to resolve this? Any specific jars/API required for this?
EDIT:
web.xml
<servlet>
<servlet-name>jersey-serlvet</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>
com.security;
com.exception
</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.spi.container.ResourceFilters</param-name>
<param-value>com.sun.jersey.api.container.filter.RolesAllowedResourceFilterFactory</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>jersey-serlvet</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
<security-constraint>
<web-resource-collection>
<web-resource-name>BasicDemo</web-resource-name>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>Admin</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<!-- The realm name is typically displayed by the browser in the login dialog box. -->
<realm-name>Login</realm-name>
</login-config>
Please let me know about the issue.
回答1:
I struggled with a similar issue for hours before one line from this IBM article opened my eyes. Surprisingly, not a single book or user guide mentions this critical fact, without which, authentication can't succeed.
When using annotation-based security, web.xml is not optional; quite on the contrary, <security-constraint> element must be present; the web container checks for security before JAX-RS does and without a <security-constraint>, the proper security context is not set. Thus when JAX-RS invokes isUserInRole(role), it always returns false.
In addition, either <security-role> element(s) in web.xml or @DeclareRoles annotation must be present.
Lastly, if using Jersey, RolesAllowedDynamicFeature needs to be registered in the Application class to enable annotation-based security.
HTH others who struggle with the pathetic documentation, or lack of it, thereof, that's out there.
回答2:
Do you have the import in your code?
import javax.annotation.security.RolesAllowed;
Also make sure annotations-api.jar is in your classpath. The jar can be found at Tomcat installation lib folder.
回答3:
Finally made it work!
Here are the steps to make it work in Tomcat and Jersey.
Let's assume we have the following contents in TOMCAT_HOME/conf/tomcat-users.xml, where we define 2 roles - editor and member.
We also define three users - gavin, julie, and admin.
<?xml version="1.0" encoding="UTF-8"?>
<role rolename="editor"/>
<role rolename="member"/>
<user username="admin" password="qwerty" roles="editor,member"/>
<user username="gavin" password="qwerty" roles="editor"/>
<user username="julie" password="qwerty" roles="member"/>
</tomcat-users>
Step 1. Make sure you use Servlet 3.0 spec in web.xml
Security annotations do not work with Servlet 2.5 and below.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
</web-app>
Step 2. Create your Application Class to enable Security Annotations
NOTE: The code below is specific to Jersey.
package ph.activelearning.rest.security;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.server.filter.RolesAllowedDynamicFeature;
public class MyApplication extends ResourceConfig {
public MyApplication() {
super(TestResource.class);
register(RolesAllowedDynamicFeature.class);
}
}
Step 3. Specify your Application Class in web.xml
Make sure that the Application class you created in Step 2 is recognized by Jersey.
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>ph.activelearning.rest.security</param-value>
</init-param>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>ph.activelearning.rest.security.MyApplication</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
Step 4. Create security-constraint in web.xml
Ironically, even though we want to use security annotations, we still need to define a security constraint in web.xml.
In the example below, we try to secure access to /test/*. It's important that you don't specify any HTTP methods. (ex. <http-method>GET</http-method>) This means that you're denying access to all HTTP methods.
Still, you need to define all roles that can have access to the URL regardless of the method, through the <auth-constraint> element.
<web-app …>
<security-constraint>
<web-resource-collection>
<web-resource-name>test</web-resource-name>
<url-pattern>/test/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>editor</role-name>
<role-name>member</role-name>
</auth-constraint>
</security-constraint>
</web-app>
Step 5. Specify authentication method in web.xml
The example below illustrates BASIC authentication.
<web-app …>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>test</realm-name>
</login-config>
</web-app>
Step 6. Define Security Roles
The security roles should correspond to the same roles defined in tomcat-users.xml. In this example, we define the roles editor and member.
NOTE: It seems that this step is optional since authentication / authorization still works even without it.
<web-app ...>
<security-role>
<description>This is editor</description>
<role-name>editor</role-name>
</security-role>
<security-role>
<description>This is member</description>
<role-name>member</role-name>
</security-role>
</web-app>
Step 7. Annotate your resources
package ph.activelearning.rest.security;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.SecurityContext;
@Path("test")
@PermitAll
public class TestResource {
@GET
@Path("editor")
@Produces(MediaType.TEXT_PLAIN)
@RolesAllowed("editor")
public String editorOnly() {
return "Got to editor path!";
}
@GET
@Path("member")
@Produces(MediaType.TEXT_PLAIN)
@RolesAllowed("member")
public String memberOnly() {
return "Got to member path!";
}
@GET
@Path("open")
@Produces(MediaType.TEXT_PLAIN)
public String open(@Context SecurityContext context) {
return "Open to all! - " + context.getUserPrincipal().getName();
}
}
That's it. Here's the complete web.xml for your programming pleasure.
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<servlet>
<servlet-name>Jersey Web Application</servlet-name>
<servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
<init-param>
<param-name>jersey.config.server.provider.packages</param-name>
<param-value>ph.activelearning.rest.security</param-value>
</init-param>
<!-- Define the Application class where we enable security annotations -->
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>ph.activelearning.rest.security.MyApplication</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>
<!-- Required even though we use annotations -->
<security-constraint>
<web-resource-collection>
<web-resource-name>test</web-resource-name>
<url-pattern>/test/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>editor</role-name>
<role-name>member</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>test</realm-name>
</login-config>
<!-- Optional: Define security roles that are defined in your app server -->
<!--
<security-role>
<description>This is editor</description>
<role-name>editor</role-name>
</security-role>
<security-role>
<description>This is member</description>
<role-name>member</role-name>
</security-role>
-->
</web-app>
回答4:
I don't know any java library that declare @RolesAllows. The Java6 EE API docs declare only 5 annotations to security use.
@DeclareRoles
@DenyAll
@PermitAll
@RolesAllowed
@RunAs
If you are trying to override the class roles, you cant simply put @RolesAllowed in your method, just like you did, I'm sure that will work.
回答5:
I think you should add the jsr250-api-1.0.jar. If you use Maven you can add this:
<dependency>
<!-- Annotations for role management -->
<groupId>javax.annotation</groupId>
<artifactId>jsr250-api</artifactId>
<version>1.0</version>
</dependency>
来源:https://stackoverflow.com/questions/15188895/rolesallowed-cannot-be-resolved-with-jersey