问题描述
我有一个JAX-RS服务,我希望所有用户都能访问我的服务,但只有那些有权查看结果的人。
例如:
- $
- 用户针对一个REST服务进行身份验证,并向他发送JWT令牌和他的ID
- 用户请求其他资源,并在每个请求中发送他的JWT及其ID。 >
- 我检查他的用户标识(来自JWT),如果业务逻辑返回结果,我将它们发送回去,否则我发送空结果集或特定的HTTP状态
问题是:我应该在哪里检查用户标识,在一些单独的过滤器,安全上下文或每个REST方法实现中?如何使用这个ID提供REST方法,可以通过ID过滤请求之后在每个方法中注入securityContext?
我使用GlassFish 4.1和Jersey JAX-RS实现。
您可以在。在这里处理自定义安全功能很常见。
需要考虑的一些事项
-
,因此它会在其他过滤器之前执行(如果有的话)。
http://docs.oracle.com/javaee/7/api/javax/ws/rs/core/SecurityContext.htmlrel =nofollow noreferrer> - 我创建了一个
SecurityContext
- 添加了一些角色,并将它们用于
isUserInRole
方法。这将用于授权。 - 我创建了一个自定义的
User
类,它实现了java。 security.Principal
。我返回了这个自定义对象 - 最后,我在
ContainerRequestContext
SecurityContext > -
SecurityContext
被注入到方法中。 - 我们得到
Principal
并将其转换为User
。所以你真的可以创建任何实现Principal
的类,然后使用这个对象。 -
使用
@RolesAllowed
注释。使用Jersey,有一个过滤器通过将@RolesAllowed
注释中的每个值传递给SecurityContext.isUserInRole
查看用户是否被允许访问资源。
要为Jersey启用此功能,我们需要注册
RolesAllowedDynamicFeature
pre $ code $ @ $ $
$ public $ AppConfig extends ResourceConfig {
public AppConfig(){
packages(packages.to.scan);
寄存器(RolesAllowedDynamicFeature.class);
}
}
- user authenticates against one REST service and I send him JWT token with his ID
- user asks for other resource and sends his JWT with his ID in each request
- I check his user id (from JWT) and if the business logic returns result I send them back, else I send empty result set or specific HTTP status
The class should be annotated with
@Priority(Priorities.AUTHENTICATION)
so it is performed before other filters, if any.You should make use of the
SecurityContext
, inside the filter. What I do is implement aSecurityContext
. You can really implement it anyway you want.- I've created a
SecurityContext
- I've added some roles, and used them for the
isUserInRole
method. This will be used for authorization. - I've created a custom
User
class, that implementsjava.security.Principal
. I returned this custom object - Finally I set the new
SecurityContext
in theContainerRequestContext
SecurityContext
is injected into the method.- We get the
Principal
and cast it toUser
. So really you can create any class that implementsPrincipal
, and use this object however you want. The use of the
@RolesAllowed
annotation. With Jersey, there is a filter that checks theSecurityContext.isUserInRole
by passing in each value in the@RolesAllowed
annotation to see if the User is allowed to access the resource.To enable this feature with Jersey, we need to register the
RolesAllowedDynamicFeature
@ApplicationPath("/api") public class AppConfig extends ResourceConfig { public AppConfig() { packages("packages.to.scan"); register(RolesAllowedDynamicFeature.class); } }
SecurityContext
,在过滤器内部。我所做的是实现 SecurityContext
。无论如何,你可以真正实现它。 下面是一个没有任何安全逻辑的简单示例
pre>
@Provider
@Priority(Priorities.AUTHENTICATION)
public class SecurityFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext requestContext)抛出IOException {
SecurityContext originalContext = requestContext.getSecurityContext();
Set< String> roles = new HashSet<>();
roles.add(ADMIN);
Authorizer authorizer = new Authorizer(roles,admin,
originalContext.isSecure());
requestContext.setSecurityContext(authorizer);
public static class Authorizer实现SecurityContext {
Set< String>角色;
字符串用户名;
boolean isSecure;
public Authorizer(设置< String>角色,最终字符串用户名,
boolean isSecure){
this.roles = roles;
this.username = username;
this.isSecure = isSecure;
}
@Override
public Principal getUserPrincipal(){
return new User(username);
}
@Override
public boolean isUserInRole(String role){
return roles.contains(role);
}
@Override
public boolean isSecure(){
return isSecure;
}
@Override
public String getAuthenticationScheme(){
returnYour Scheme;
}
}
public static class User implements Principal {
String name;
public User(String name){
this.name = name;
}
@Override
public String getName(){return name; }
}
}
有几件事要注意
现在呢?让我们看看一个简单的资源类。
$ p $ @Path(secure)
public class SecuredResource {
@GET
@RolesAllowed({ADMIN})
public String getUsername(@Context SecurityContext securityContext){
User user =(User)securityContext.getUserPrincipal();
返回user.getName();
有几点需要注意:
I have a JAX-RS service where I want all my users to access my services, but just those who have rights to see the result. Roles based security and existing REALMS and atuhentication methods doesn't fit my requirement.
For example:
Question is: Where should I check for users ID, in some separate filter, security context or in every REST method implementation? How to provide REST methods with this ID, can securityContext be injected in every method after filtering request by ID?
I'm using GlassFish 4.1 and Jersey JAX-RS implementation.
You can perform this logic in a ContainerRequestFilter
. It pretty common to handle custom security features in here.
Some things to consider
Here's a simple example without any of the security logic
@Provider
@Priority(Priorities.AUTHENTICATION)
public class SecurityFilter implements ContainerRequestFilter {
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
SecurityContext originalContext = requestContext.getSecurityContext();
Set<String> roles = new HashSet<>();
roles.add("ADMIN");
Authorizer authorizer = new Authorizer(roles, "admin",
originalContext.isSecure());
requestContext.setSecurityContext(authorizer);
}
public static class Authorizer implements SecurityContext {
Set<String> roles;
String username;
boolean isSecure;
public Authorizer(Set<String> roles, final String username,
boolean isSecure) {
this.roles = roles;
this.username = username;
this.isSecure = isSecure;
}
@Override
public Principal getUserPrincipal() {
return new User(username);
}
@Override
public boolean isUserInRole(String role) {
return roles.contains(role);
}
@Override
public boolean isSecure() {
return isSecure;
}
@Override
public String getAuthenticationScheme() {
return "Your Scheme";
}
}
public static class User implements Principal {
String name;
public User(String name) {
this.name = name;
}
@Override
public String getName() { return name; }
}
}
A few things to notice
Now what? Let's look at a simple resource class
@Path("secure")
public class SecuredResource {
@GET
@RolesAllowed({"ADMIN"})
public String getUsername(@Context SecurityContext securityContext) {
User user = (User)securityContext.getUserPrincipal();
return user.getName();
}
}
A few things to notice:
这篇关于自定义JAX-RS授权 - 在每个请求中使用JWT的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!