Java+MicroProfile:如何实现无授权的身份认证?
解决方案
要实现仅强制MP-JWT身份认证(不进行角色授权),你需要明确要求所有请求必须经过身份验证——默认情况下JAX-RS端点在未添加安全注解时是公开的。以下是可行的解决方法:
方法一:使用JAX-RS过滤器强制身份认证
创建全局请求过滤器,检查每个请求的SecurityContext是否存在已认证的用户主体。如果不存在,则返回401未授权响应。
步骤1:实现过滤器
import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerRequestFilter; import javax.ws.rs.core.Response; import javax.ws.rs.ext.Provider; @Provider public class AuthEnforcementFilter implements ContainerRequestFilter { @Override public void filter(ContainerRequestContext requestContext) { // 检查是否存在已认证的用户主体 if (requestContext.getSecurityContext().getUserPrincipal() == null) { requestContext.abortWith( Response.status(Response.Status.UNAUTHORIZED) .header("WWW-Authenticate", "Bearer realm=\"your-service-realm\"") .build() ); } } }
步骤2:注册过滤器
在你的Application子类中注册该过滤器:
import javax.ws.rs.ApplicationPath; import javax.ws.rs.core.Application; import java.util.HashSet; import java.util.Set; @ApplicationPath("/api") @LoginConfig(authMethod = "MP-JWT") public class MyApplication extends Application { @Override public Set<Class<?>> getClasses() { Set<Class<?>> classes = new HashSet<>(); // 添加你的资源类 classes.add(YourResource.class); // 注册身份认证过滤器 classes.add(AuthEnforcementFilter.class); return classes; } }
这个过滤器会拦截所有请求,确保只有携带有效MP-JWT令牌的请求才能通过。由于你已配置@LoginConfig(authMethod = "MP-JWT"),Payara会自动验证令牌有效性并设置SecurityContext中的用户主体——如果令牌无效或缺失,主体会为null,过滤器将返回401。
为什么之前的尝试不生效?
@LoginConfig(authMethod = "MP-JWT")仅指定了身份认证方式,不会自动保护所有端点。端点默认公开,只有添加@RolesAllowed、@DenyAll等注解时才会触发身份认证。- 你尝试的Payara配置
payara.microprofile.jwt.rolesAllowed.enabled=false是用来禁用角色授权检查(忽略@RolesAllowed注解),但它不会强制所有端点进行身份认证,因此无法解决你的问题。
替代方案(不推荐)
如果你的Google JWT令牌包含固定角色(如自定义声明),可以在Application类上添加@RolesAllowed("*"),但这要求所有令牌至少包含一个角色。由于Google隐式流生成的令牌可能没有MP-JWT默认映射角色的groups声明,这种方法还需额外配置mp.jwt.token.claim.group.name指定其他声明作为角色来源,灵活性远不如过滤器方法。
内容的提问来源于stack exchange,提问作者mmb
相关产品推荐
相关产品推荐

