gpt4 book ai didi

java - 自定义 JAX-RS 授权 - 在每个请求中使用 JWT

转载 作者:搜寻专家 更新时间:2023-10-30 21:40:52 24 4
gpt4 key购买 nike

我有一个 JAX-RS 服务,我希望我的所有用户都可以访问我的服务,但只有那些有权查看结果的用户。基于角色的安全性以及现有的 REALMS 和验证方法不符合我的要求。

例如:

  1. 用户针对一项 REST 服务进行身份验证,我将 JWT token 和他的 ID 发送给他
  2. 用户请求其他资源并在每个请求中发送他的 JWT 和他的 ID
  3. 我检查他的用户 ID(来自 JWT),如果业务逻辑返回结果,我将它们发回,否则我发送空结果集或特定的 HTTP 状态

问题是:我应该在哪里检查用户 ID,是在某个单独的过滤器、安全上下文中还是在每个 REST 方法实现中?如何给REST方法提供这个ID,通过ID过滤请求后securityContext是否可以在每个方法中注入(inject)?

我正在使用 GlassFish 4.1 和 Jersey JAX-RS 实现。

最佳答案

您可以在 ContainerRequestFilter 中执行此逻辑.在这里处理自定义安全功能很常见。

一些需要考虑的事情

  1. 该类应使用 @Priority(Priorities.AUTHENTICATION) 进行注释所以它在其他过滤器之前执行,如果有的话。

  2. 你应该使用 SecurityContext , 过滤器内部。我所做的是实现一个 SecurityContext。您可以随心所欲地实现它。

这是一个没有任何安全逻辑的简单示例

@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; }
}
}

注意事项

  • 我已经创建了一个SecurityContext
  • 我添加了一些角色,并将它们用于 isUserInRole 方法。这将用于授权。
  • 我创建了一个自定义的 User 类,它实现了 java.security.Principal。我归还了这个自定义对象
  • 最后,我在 ContainerRequestContext 中设置了新的 SecurityContext

现在呢?我们来看一个简单的资源类

@Path("secure")
public class SecuredResource {
@GET
@RolesAllowed({"ADMIN"})
public String getUsername(@Context SecurityContext securityContext) {
User user = (User)securityContext.getUserPrincipal();
return user.getName();
}
}

需要注意的几点:

  • SecurityContext 被注入(inject)到方法中。
  • 我们得到 Principal 并将其转换为 User。因此,您实际上可以创建任何实现 Principal 的类,并根据需要使用该对象。
  • @RolesAllowed 注释的使用。对于 Jersey,有一个过滤器通过传入 @RolesAllowed 注释中的每个值来检查 SecurityContext.isUserInRole 以查看是否允许用户访问资源。

    要使用 Jersey 启用此功能,我们需要注册 RolesAllowedDynamicFeature

    @ApplicationPath("/api")
    public class AppConfig extends ResourceConfig {

    public AppConfig() {
    packages("packages.to.scan");
    register(RolesAllowedDynamicFeature.class);
    }
    }

关于java - 自定义 JAX-RS 授权 - 在每个请求中使用 JWT,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29766673/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com