java - java中Restful端点上基于角色的身份验证
问题描述
我正在尝试实现某种基于角色的身份验证。我正在使用 JWT 令牌。我一直在看指南,但他们都提到了“Spring boot”的使用。如何在 Java 中的 restful 端点上设置基于角色的身份验证?最好通过某种过滤器。
我正在寻找一种方法来简单地添加:@Role(Role.ADMIN)
在端点之前。
我已经设置了以下课程:
枚举角色:
public enum Role { User, Admin }
简单的 JWT 令牌:
{ "sub": "users/TzMUocMF4p", "exp": 1554646441, "username": "username@gmail.com", "ID": 6, "Role": "Admin", "iat": 1554641041 }
简单的 CRUD 端点
@Path("User") public class UserResource { @EJB private UserDAO userappDAO; @GET @JWTTokenNeeded @Produces("application/json") public List<Userapp> all() { return userappDAO.getAll(); } }
JWT 验证 (
@JWTTokenNeeded
) 类如下:@javax.ws.rs.NameBinding @Retention(RUNTIME) @Target({TYPE, METHOD}) public @interface JWTTokenNeeded { }
实际过滤器:
@Provider @JWTTokenNeeded @Priority(Priorities.AUTHENTICATION) public class JWTTokenNeededFilter implements ContainerRequestFilter { @Override public void filter(ContainerRequestContext requestContext) throws IOException { // Get the HTTP Authorization header from the request String authorizationHeader = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION); try { // Extract the token from the HTTP Authorization header String token = authorizationHeader.substring("Bearer".length()).trim(); // Validate the token Jwts.parser().setSigningKey("MYSECRET".getBytes("UTF-8")).parseClaimsJws(token); } catch (Exception e) { requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build()); } } }
如果用户未经授权,我想退出:
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
如果用户被授权,端点必须这样做。
解决方案
我找到了一个可行的解决方案。@JWTTokenNeeded
它包括向接口和类添加几行JWTTokenNeededFilter
。
我最终得到以下代码:
JWTTokenNeededFilter:
@Provider
@JWTTokenNeeded
@Priority(Priorities.AUTHENTICATION)
public class JWTTokenNeededFilter implements ContainerRequestFilter {
@Context
private ResourceInfo resourceInfo;
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
// Get the HTTP Authorization header from the request
String authorizationHeader = requestContext.getHeaderString(HttpHeaders.AUTHORIZATION);
try {
// Extract the token from the HTTP Authorization header
String token = authorizationHeader.substring("Bearer".length()).trim();
// Validate the token
Claims claims = Jwts.parser().setSigningKey("MYSECRET".getBytes("UTF-8")).parseClaimsJws(token).getBody();
Method method =resourceInfo.getResourceMethod();
if( method != null){
// Get allowed permission on method
JWTTokenNeeded JWTContext = method.getAnnotation(JWTTokenNeeded.class);
Role permission = JWTContext.Permissions();
if(permission != Role.NoRights ) {
// Get Role from jwt
String roles = claims.get("Role", String.class);
Role roleUser = Role.valueOf(roles);
// if role allowed != role jwt -> UNAUTHORIZED
if (!permission.equals(roleUser)) {
throw new Exception("no roles");
}
}
}
}
catch (Exception e) {
e.printStackTrace();
requestContext.abortWith(Response.status(Response.Status.UNAUTHORIZED).build());
}
}
}
@JWTTokenNeeded 接口:
@javax.ws.rs.NameBinding
@Retention(RUNTIME)
@Target({TYPE, METHOD})
public @interface JWTTokenNeeded {
Role Permissions() default Role.NoRights;
}
允许角色访问端点就像添加一样简单@JWTTokenNeeded(Permissions = Role.Admin)
这是一个例子:
@Path("User")
public class UserResource {
@EJB
private UserappDAO userDAO;
@GET
@JWTTokenNeeded(Permissions = Role.Admin)
@Produces("application/json")
public List<Userapp> all() {
return userDAO.getAll();
}
}
推荐阅读
- django - django-auditlog 不适用于用户模型
- python - Python 4路视频流程序QThread提速问题
- mysql - 如何从两个不同模式的两个表中找到增量
- python-3.x - Python 3将加密的字节字符串写入文件
- sql-server - 无法使用安全套接字层 (SSL) 建立安全连接的 MsSQL 驱动程序?
- html - 这段代码中的高度和最小高度有什么区别?
- android - 创建回收站视图项目动画
- reactjs - 如何等到 useContext 中的状态完全加载?
- go - 如何从错误本身获取错误代码“os.ErrNotExist”?
- c# - Blazor、blazor js 和其他 js 抛出错误