如何在泽西岛对用户进行身份验证
我正在使用 Jersey 用 Java 编写一个 RESTful 应用程序,我需要对用户进行身份验证.我知道我可以使用注释@RolesAllowed 指定资源中的角色,但我无法理解用户如何与特定角色相关联.客户端这样发送用户名和密码
I am writing a RESTful application in Java using Jersey, and i need to authenticate users. I know i can specify the roles in the resource using the annotations @RolesAllowed, but i can't understand how a user is associated to a specific role. The client sends username and password in this way
HttpAuthenticationFeature feature = HttpAuthenticationFeature.basic(user, password);
Client client = ClientBuilder.newClient();
client.register(feature);
WebTarget target = client.target(baseUrl).path(urlString);
Invocation.Builder invocationBuilder = target.request(MediaType.APPLICATION_JSON);
Response response = invocationBuilder.get();
假设有些方法只能由超级用户使用,有些方法可以由任何用户使用,那么当客户端发送用户名和密码时,如何区分它们?
Supposing that some methods can be used only by superusers and others by any user, how can i distinguish them when the username and the password are sent by the client?
推荐答案
我知道我可以使用注释 @RolesAllowed 指定资源中的角色,但我不明白用户是如何与特定角色相关联的
I know i can specify the roles in the resource using the annotations @RolesAllowed, but i can't understand how a user is associated to a specific role
角色信息存储在数据库中.假设你有一个 User
对数据库中的 USER 和 ROLES 表进行建模
The role information is stored in the DB. Assuming say you have a User
that models the USER and ROLES table in the DB
class User {
String username;
List<String> roles;
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public List<String> getRoles() { return roles; }
public void setRoles(List<String> roles) { this.roles = roles; }
}
您将在 Jersey 过滤器中获得 User
.这也是您进行身份验证的地方.
You would get the User
inside a Jersey filter. This is also where you would authenticate.
@Provider
@Priority(Priorities.AUTHENTICATION) // needs to happen before authorization
class AuthenticationFilter implements ContainerRequestFilter {
@Inject
private UserService userService; // this is your own service
@Override
public void filter(ContainerRequestContex context) {
// note, this is a lazy implementation of Basic auth.
// it doesn't do ant error checking. Please see
// link at bottom for better imlementation
String authzHeader = context.getHeaderString(HttpHeaders.AUTHORIZATION); // (1)
String decoded = Base64.decodeAsString(authzHeader);
String[] split = decoded.split(":");
User user = userService.getUser(split[0]); // (2)
if (user == null || !user.getPassword().equals(someHash(split[1])) { // (3)
throw new UnauthorizedException();
}
SecurityContext oldContext = context.getSecurityContext(); // (4)
context.setSecurityContext(new BasicSecurityConext(user, oldContext.isSecure()));
}
}
你在这里做的是:
- 解析 Basic Auth Authorization 标头
- 使用用户名获取
User
- 进行身份验证
- 设置一个新的
SecurityContext
.
BasicSecurityContext
如下所示.这是您将角色与用户相关联的地方.
The BasicSecurityContext
is shown below. This is where you will associate roles with the user.
static class BasicSecurityContext implements SecurityContext {
private final User user;
private final boolean secure;
public BasicSecurityContext(User user, boolean secure) {
this.user = user;
this.secure = secure;
}
@Override
public Principal getUserPrincipal() {
return new Principal() {
@Override
public String getName() {
return user.getUsername();
}
};
}
@Override
public String getAuthenticationScheme() {
return SecurityContext.BASIC_AUTH;
}
@Override
public boolean isSecure() { return secure; }
@Override
public boolean isUserInRole(String role) {
return user.getRoles().contains(role);
}
}
如果您查看 isUserInRole
的底部.将会发生的是,Jersey 将从资源方法或类中获取 @RolesAllowed
注释,获取值,然后将它们传递给 isUserInRole
.如果它返回true
,则用户被授权.在伪代码中
If you look at the bottom at the isUserInRole
. What will happen is that Jersey will grab the @RolesAllowed
annotation from the resource method or class, grab the values, then pass them to the isUserInRole
. If it returns true
, then the user is authorized. In pseudo-code
@GET
@Path("/somepath")
@RolesAllowed({"USER", "SUPER_USER"})
public Response get() {}
...
RolesAllowed annotation = resourceMethod.getAnnotation(RolesAllowed.class);
String roles = annotation.value();
SecurityContext context = getSecurityContext();
for (String role: roles) {
if (context.isUserInRole(role)) {
return;
}
}
throw new ForbiddenException();
这只是伪代码,但它显示了 Jersey 如何使用 @RolesAllowed
、SecurityContext
处理授权,以及如何实现 isUserInRole
.
This is just pseudo-code, but it shows how Jersey handles the authorizaiton, using the @RolesAllowed
, the SecurityContext
, and how you implement the isUserInRole
.
此授权功能不会自动开启.你需要自己打开它.为此,只需注册 RolesAllowedDynamicFeature
This authorization feature is not automatically turned on. You need to turn it on yourself. To do so, simply register the RolesAllowedDynamicFeature
public JerseyConfig extends ResourceConfig {
public JerseyConfig() {
register(RolesAllowedDynamicFeature.class);
}
}
这里要注意的一点是,在上述所有内容中,我们都在实施基本的身份验证和安全上下文的设置.这并没有什么问题.但是如果你使用 servlet 容器身份验证机制,Jersey 实际上会从 HttpServletRequest
中获取身份验证信息.HttpServletRequest
有一个 getUserPrincipal()
方法和一个 isUserInRole
方法.Jersey 将使用这些在 SecurityContext
中进行委托.因此,如果您是用户容器身份验证,那么您实际上不需要实现任何东西.您只需要注册 RolesAllowedDynamicFeature
One thing to note here is that in all of the above, we are implementing our basic authentication and setting of the security context. There is nothing really wrong with this. But if you are using the servlet container authentication mechanism, Jersey will actually take the auth information from the HttpServletRequest
. The HttpServletRequest
has a getUserPrincipal()
method and a isUserInRole
method. Jersey will use these to delegate in the SecurityContext
. So if you are user the container authentication, then you don't really need to implement anything. You just need to register the RolesAllowedDynamicFeature
如果您想使用容器的身份验证机制,您应该查阅服务器的文档.在您的服务器中设置领域后,您需要使用安全信息配置 web.xml
.下面的链接中有一个示例.您还应该在 Web 安全部分下的 Java EE 文档中找到此信息.
If you want to use your container's authentication mechanism, you should consult your server's documentation. After having set up a realm in with your server, you will then need to configure the web.xml
with the security information. There's an example in the link below. You should also find this information in the Java EE docs under the web security section.
另请参阅:
- 过滤器和拦截器 了解有关使用过滤器的更多信息.
- 安全了解更多有关在泽西岛从事安保工作的信息.
- 基本身份验证过滤器的更好实现
- Jersey 2 中的 ResourceConfig 类到底是什么?
- Filter and Interceptors to learn more about working with filters.
- Security for a little more info on working with security in Jersey.
- A better implementation of the basic auth filter
- What exactly is the ResourceConfig class in Jersey 2?
相关文章