我想验证一个发出请求的用户。为此,我有两个过滤器:AuthenticationFilter和authorizationfilter。AuthenticationFilter从请求中提取令牌并从数据库中查找用户。AuthorizationFilter检查该用户(由上一个筛选器检索)是否具有必要的权限。我有两个可能的解决方案,想知道每一个的利弊,我应该使用哪一个。我还需要访问实际业务逻辑中的用户。我的代码如下:
AuthenticationFilter:
@Secured
@Provider
@Priority(Priorities.AUTHENTICATION)
public class AuthenticationFilter implements ContainerRequestFilter {
// option 1.1
@Inject
@AuthenticatedUser
private Event<User> authenticatedUserEvent;
// option 1.2
@Inject
@AuthenticatedUser
private User authenticatedUser;
public void filter(ContainerRequestContext requestContext) throws IOException {
String token = getToken(requestContext);
User user = getUser(token)
if (user == null) {
requestContext.abortWith(...);
} else {
// option 1.1
authenticatedUserEvent.fire(User);
// option 1.2
authenticatedUser.setData(user);
// option 2
requestContext.setProperty("authenticatedUser", user);
}
}
}
AuthorizationFilter:
@Secured
@Provider
@Priority(Priorities.AUTHORIZATION)
public class AuthorizationFilter implements ContainerRequestFilter {
@Context
private ResourceInfo resourceInfo;
// option 1
@Inject
@AuthenticatedUser
private User authenticatedUser;
public void filter(ContainerRequestContext requestContext) throws IOException {
// option 2
User authenticatedUser = (User) requestContext.getProperty("authenticatedUser")
boolean allowed = verifyRoles(user, resourceInfo.getResourceClass(), resourceInfo.getResourceMethod());
if (!allowed) {
requestContext.abortWith(...);
}
}
}
AuthenticatedUserProducer(仅用于选项1):
@RequestScoped
public class AuthenticatedUserProducer {
@Produces
@RequestScoped
@AuthenticatedUser
private User authenticatedUser;
public void handleAuthenticationEvent(@Observes @AuthenticatedUser User user) {
this.authenticatedUser = user
}
}
对于选项1,是否有必要使用@requestscoped
注释筛选器?默认情况下,过滤器是应用范围的,那么注入是安全的吗?即,如果同时处理多个请求,则由请求链1中的过滤器1触发的事件将不会被注入链2的过滤器2中?在实际业务逻辑运行的资源类中注入用户时也是如此?
对于选项2,我不再有权访问ContainerRequestContext
,但可以通过注入HttpServletRequest
来访问对象。但是这个选项在我看来“不太干净”,因为我必须在使用之前将存储的对象转换给用户,而当使用注入方法时,我可以直接使用对象。
我已经检查了这些问题,我正在寻找的是确定哪个选项是最好的:
我目前使用的是WildFly11,它的默认实现是JAX-RS(Resteasy)和CDI(Weld)。
执行身份验证/授权之后,就可以使用securitycontext
,这是JAX-RS API的一部分。请参阅如何在身份验证筛选器中使用它的示例:
final SecurityContext currentSecurityContext = requestContext.getSecurityContext();
requestContext.setSecurityContext(new SecurityContext() {
@Override
public Principal getUserPrincipal() {
// Return a Principal instance according to your needs
return () -> username;
}
@Override
public boolean isUserInRole(String role) {
return true;
}
@Override
public boolean isSecure() {
return currentSecurityContext.isSecure();
}
@Override
public String getAuthenticationScheme() {
// Return the authentication scheme used by your application
return SecurityContext.BASIC_AUTH;
}
});
然后使用@context
注释将SecurityContext
注入到JAX-RS资源和提供程序中:
@Context
SecurityContext securityContext;
然后您可以获得SecurityContext
中设置的Principal
实例:
Principal principal = securityContext.getUserPrincipal();
问题内容: 我有一个关于JAX-RS的非常基本的问题,但我无法以某种方式轻易找到答案。 我正在尝试将使用“标准” Javax servlet的REST服务重构为“手工”将请求路由到方法的“ REST服务”,使其成为“更干净的” JAX- RS实现。当前应用程序在servlet init()期间设置一些变量。它将那些属性分配为HttpServlet类的属性,因此它们在每个doGet()期间都可用,并
问题内容: 我有一个活动,这是整个应用程序中使用的主要活动,它具有许多变量。我还有另外两个活动,我希望能够使用第一个活动中的数据。现在我知道我可以做这样的事情: 但是我想共享很多变量,有些可能很大,所以我不想像上面那样创建它们的副本。 有没有一种方法可以直接获取和更改变量而无需使用get和set方法?我记得在Google开发者网站上读过一篇文章,建议不要在Android上使用此功能。 问题答案:
问题内容: “无效”是指不期望的参数。 例如: 然后我打电话 问题答案: 您可以检查使用ContainerRequestFilter并将传递的参数与定义的参数进行比较: 不要忘记ServletRequest#getParameterMap返回一个Map,该Map包含查询字符串参数和在请求正文中传递的参数。因此,也许您需要自己解析查询字符串。 注意:这不会加快您的应用程序的速度。
在JAX-RS(RestEasy)中,我希望实现一个客户机过滤器,在发送请求之前修改头,这样我就不会对每个调用都手动执行此操作。 目前,我正在接收端执行此操作,以便在到达资源之前拦截请求。
有没有人知道Docker中容器之间共享数据库的最佳实践是什么? 我的意思是我想在Docker中创建多个容器。然后,这些容器将以相同的身份在相同的数据库上执行CRUD。 到目前为止,我有两个想法。一种是创建一个单独的容器来运行数据库。另一种方法是直接在安装Docker的主机上安装数据库。
问题内容: 我有一项从服务器中获取一些客户端数据的服务: 然后在一个控制器中执行: 一切都很好。但是,我正在尝试从该服务上的另一个控制器进行监视,以在数据更改时更新其范围,而不是必须重新启动http请求: 我现在只是提醒,但从未触发过。页面最初加载时,它会发出“未定义”警报。我在控制台中没有任何错误,并且所有$ injects都很好,但是似乎从未意识到服务中的数据已更改。我在手表上做错了吗? 非常