gpt4 book ai didi

java - 将 @RolesAllowed 注释应用于数据库中存储的现有用户

转载 作者:行者123 更新时间:2023-12-02 00:47:05 27 4
gpt4 key购买 nike

TLDR我开发的Java Web应用程序需要在REST服务上实现用户区分。我知道有一些注释(@RolesAllowed@PermitAll@DenyAll)可以描述哪个角色可以使用该服务。我的问题是,如何将 @RolesAllowed 中的角色与用户角色枚举相匹配,该用户是存储在数据库中的持久对象?

许多教程都解释了@RolesAllowed,但我发现没有一个与这些角色匹配,以及已经创建的角色

<小时/>

说明

如何通过自动检查用户的角色(通​​过 session ID 找到)来验证用户?我知道 Jersey 已经通过注册 RolesAllowedDynamicFeature.class 来做到这一点。我已经设法通过将 @DenyAll 注释放入方法中来检查此 RolesAllowedDynamicFeature.class 是否有效,并返回 403 错误。

首先我们先来了解一下什么是用户。用户是数据库实体,使用 Ebean 将它们保存在 Java 对象中或保存到 Java 对象中。以下是来自 User.class 的示例:

/*
* A sample that describes the fields that I ask for and to understand the concept
*/
@Entity
@Table(name = "users")
public class User extends Model
{
@Id
@GeneratedValue
@Column(name = "id")
private long id;

@Enumerated(EnumType.STRING)
@Column(name = "role", nullable = false)
private UserRole role;

// contructors getters setters helper methods etc

/**
* Fetch a user from DB
*
* @param id the id to search for
* @return a Person.class object or may return null
*/
public static User getUserById(Long id)
{
return Ebean.find(User.class, id);
}

/* and here is the UserRole enum that define the roles every user can have */
public static enum UserRole
{
Administrator, User, Manager;
}
}

以上所有代码都工作正常,用户存储正确,我可以轻松获取它们。

每个用户在登录时都会使用类似的服务进行身份验证,并为每个用户创建一个具有唯一 session ID(使用 UUID)的 ConnectedUser 对象。每次服务调用后,都会运行一个身份验证,如果该 session 有连接的用户条目(存储为 cookie),则验证用户是否可以通过搜索使用该服务:

@Secured
@Provider
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter
{
@Context
private HttpServletRequest request;

/**
* Authenticates a user's access with every request that is made via a token.
*
* @param requestContext The request that is sent to the server.
* @throws IOException
*/
@Override
public void filter(ContainerRequestContext requestContext) throws IOException
{
boolean isValidated;

Cookie sessionCookie = null;
Cookie[] cookies = request.getCookies();

if (cookies.length != 0) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals("CookieName")) {
sessionCookie = cookie;
}
}
}

if (sessionCookie != null) {
// UserValidationHandler checks if user is in connected_users table
isValidated = UserValidationHandler.validateUser(sessionCookie.getValue(), request.getRemoteAddr());
}
else {
MultivaluedMap pathParameters = requestContext.getUriInfo().getQueryParameters();

// UserValidationHandler checks if user is in connected_users table
isValidated = UserValidationHandler.validateUser((String)pathParameters.getFirst("token"), request.getRemoteAddr());
}

if (!isValidated) {
LOGGER.warn("[Authorization filter] Unauthorized user.");
URI indexURI = URI.create("http://login.jsp");
requestContext.setRequestUri(indexURI);
}
}
}
<小时/>

注释:

注1:大多数实现建议将角色应用到 web.xml 文件中。但我认为,就我的情况而言,这是不可行的。

注2:另外,授权用户使用服务的正确位置在哪里?我发现我可以使用 @Priority(Priorities.AUTHORIZATION) 创建 ContainerRequestFilter 类。做什么比较好?

我有点迷失在这里。我读了很多 Q/As 或示例,但没有任何解释透彻。

最佳答案

您应该将关注点分开,并在一个过滤器中进行身份验证,并在一个过滤器中进行授权。一般来说,这是通过从身份验证过滤器内部设置 SecurityContext 来实现的,然后从授权过滤器内部检索它。

SecurityContext 有一个您可以重写的 isUserInRole 方法。应在授权过滤器中调用此方法。通常,您将拥有作为 SecurityContext 成员的角色,并且只需迭代角色

static class MySecurityContext implements SecurityContext {
private final String[] userRoles;

public MySecurityContext(String[] roles, String user) {
this.userRoles = roles;
}

@Override
public Principal getUser() {
return new Principal() {
@Override
public String getName() {
return name;
}
}
}

public boolean isUserInRole(String role) {
for (String userRole: userRoles) {
if (role.equals(userRole) {
return true;
}
}
return false;
}

// more methods to override
}

在身份验证过滤器中,您只需调用传入新的 SecurityContextrequestContext.setSecurityContext 方法即可。

在授权过滤器中,您可以使用ResourceInfo 获取@RolesAllowed 注释。例如

class AuthorizationFilter implement ContainerRequestContext {
@Context
private ResourceInfo info;

@Override
public void filter(ContainerRequestContext request) {
SecurityContext sc = request.getSecurityContext();
RolesAllowed anno = info.getResourceMethod().getAnnotation(RolesAllowed.class);
String rolesAllowed = anno.value();
for (role: rolesAllowed) {
if (sc.isUserInRole(role)) {
return;
}
}
request.abortWith(Response.status(403).build());
}
}

或者类似的东西。

如果您使用 Jersey2,则不需要自己实现授权。这已经在 RolesAllowedDynamicFeature 中实现了。您只需在您的应用程序中注册该功能即可。它的工作原理与我之前提到的相同; SecurityContext 预计在到达授权过滤器之前被填充,过滤器将检查角色并授权或拒绝。

关于java - 将 @RolesAllowed 注释应用于数据库中存储的现有用户,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46359880/

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