servlet 以编程方式设置身份验证
servlet programmatically set authentication
在 JAVA EE 7 网络应用程序 (WAR) 中,需要 "manually" 将用户设置为经过身份验证的 (及其角色).
基本上我有一个令牌(JWT)和一组角色(调用Keycloak授权客户端后获得Java API)。
获得令牌后,我想将用户设置为经过身份验证(创建安全上下文),因此对安全 URL 的任何调用都不会 return 403 HTTP 错误。
在 web.xml 中定义了不同 URL 映射的角色和安全限制。
已查看 HttpServletRequest.authenticate 方法但尚未定义(不需要)登录配置机制。
(未使用 Spring 或其他框架)。
我猜这是不可能的,应该使用 servlet 过滤器来验证安全性(不是 web.xml 中的安全约束)
谢谢
您需要定义一个登录配置。对于 servlet 容器来说是必需的。
放这样的东西:
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>default</realm-name>
</login-config>
在您的 web.xml 和 HttpServletRequest.authenticate 中应该可以。
并且您应该删除此 servlet 的安全限制
因为您管理应用程序中的安全性(如果尚未完成的话)。
亲切的问候,
拉尔夫
我最初的解决方案是创建一个 servlet 过滤器,如果 JWT 令牌(来自授权 header)没有所需的角色,则 returns 未授权。
更好的方法是创建一个唯一的过滤器,为每个需要授权的请求创建安全上下文。有了这个,我可以使用 @RolesAllowed 注释。
要使 RolesAllowed 注释起作用(否则允许所有请求),重要的是添加 web.xml:
<context-param>
<param-name>resteasy.role.based.security</param-name>
<param-value>true</param-value>
</context-param>
我不能在 web.xml 中定义任何 auth-constraints ,否则应用程序 returns 403 Forbidden before the filter gets called.
安全过滤器:
@Provider
@Priority(Priorities.AUTHENTICATION)
public class SecurityFilter implements ContainerRequestFilter {
@Context private HttpServletRequest httpRequest;
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
SecurityContext originalContext = requestContext.getSecurityContext();
// 1. Get token from the request header: "Authorization: Bearer ..."
String token = httpRequest.getHeader("Authorization").substring(7);
// 2. Parse the token to an AccessToken
// calls a utility class which uses org.keycloak.TokenVerifier to get the access token
AccessToken accessToken = KeyCloakUtils.getAccessToken(token);
// 3.- Obtain username and roles
String username = accessToken.getPreferredUsername();
Set<String> roles = accessToken.getRealmAccess().getRoles();
SecurityContext sc = new SecurityContext() {
@Override
public Principal getUserPrincipal() {
return new User(username);
}
@Override
public boolean isUserInRole(String role) {
return roles.contains(role);
}
@Override
public boolean isSecure() {
return originalContext.isSecure();
}
@Override
public String getAuthenticationScheme() {
return "Your Scheme";
}
};
requestContext.setSecurityContext(sc);
}
}
安全方法示例(接口):
@POST
@Consumes({ "application/json" })
@Produces({ "application/json" })
@RolesAllowed({"ADMIN_USER"})
public Response createUser(User user);
在 JAVA EE 7 网络应用程序 (WAR) 中,需要 "manually" 将用户设置为经过身份验证的 (及其角色).
基本上我有一个令牌(JWT)和一组角色(调用Keycloak授权客户端后获得Java API)。
获得令牌后,我想将用户设置为经过身份验证(创建安全上下文),因此对安全 URL 的任何调用都不会 return 403 HTTP 错误。
在 web.xml 中定义了不同 URL 映射的角色和安全限制。
已查看 HttpServletRequest.authenticate 方法但尚未定义(不需要)登录配置机制。
(未使用 Spring 或其他框架)。
我猜这是不可能的,应该使用 servlet 过滤器来验证安全性(不是 web.xml 中的安全约束)
谢谢
您需要定义一个登录配置。对于 servlet 容器来说是必需的。 放这样的东西:
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>default</realm-name>
</login-config>
在您的 web.xml 和 HttpServletRequest.authenticate 中应该可以。
并且您应该删除此 servlet 的安全限制 因为您管理应用程序中的安全性(如果尚未完成的话)。
亲切的问候,
拉尔夫
我最初的解决方案是创建一个 servlet 过滤器,如果 JWT 令牌(来自授权 header)没有所需的角色,则 returns 未授权。
更好的方法是创建一个唯一的过滤器,为每个需要授权的请求创建安全上下文。有了这个,我可以使用 @RolesAllowed 注释。
要使 RolesAllowed 注释起作用(否则允许所有请求),重要的是添加 web.xml:
<context-param>
<param-name>resteasy.role.based.security</param-name>
<param-value>true</param-value>
</context-param>
我不能在 web.xml 中定义任何 auth-constraints ,否则应用程序 returns 403 Forbidden before the filter gets called.
安全过滤器:
@Provider
@Priority(Priorities.AUTHENTICATION)
public class SecurityFilter implements ContainerRequestFilter {
@Context private HttpServletRequest httpRequest;
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
SecurityContext originalContext = requestContext.getSecurityContext();
// 1. Get token from the request header: "Authorization: Bearer ..."
String token = httpRequest.getHeader("Authorization").substring(7);
// 2. Parse the token to an AccessToken
// calls a utility class which uses org.keycloak.TokenVerifier to get the access token
AccessToken accessToken = KeyCloakUtils.getAccessToken(token);
// 3.- Obtain username and roles
String username = accessToken.getPreferredUsername();
Set<String> roles = accessToken.getRealmAccess().getRoles();
SecurityContext sc = new SecurityContext() {
@Override
public Principal getUserPrincipal() {
return new User(username);
}
@Override
public boolean isUserInRole(String role) {
return roles.contains(role);
}
@Override
public boolean isSecure() {
return originalContext.isSecure();
}
@Override
public String getAuthenticationScheme() {
return "Your Scheme";
}
};
requestContext.setSecurityContext(sc);
}
}
安全方法示例(接口):
@POST
@Consumes({ "application/json" })
@Produces({ "application/json" })
@RolesAllowed({"ADMIN_USER"})
public Response createUser(User user);