如何在 Java Servlet 上触发 OAuth/OpenID 身份验证并将我自己的角色添加到用户?
How can I trigger OAuth/OpenID authentication on a Java Servlet and add my own roles to the user?
在本地 Wildfly 服务器上,我有一个简单的 Java servlet,如下所示:
import javax.servlet.annotation.HttpMethodConstraint;
import javax.servlet.annotation.ServletSecurity;
import javax.servlet.http.HttpServlet;
@ServletSecurity(httpMethodConstraints = { @HttpMethodConstraint(value = "GET", rolesAllowed = { "debug" })})
public class DebugServlet extends HttpServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
try ( PrintWriter out = response.getWriter()) {
/* TODO output your page here. You may use following sample code. */
...
Principal user = request.getUserPrincipal();
out.println("<p>" + (user != null ? user.getName() : "No user") + "</p>");
...
}
}
}
我已经通过第三方身份验证服务器使用 OpenID Connect (OIDC) 设置了 Wildfly 的 Elytron v1.17.2 身份验证。如果重要的话,它是 而不是 Keycloak 服务器,更改 auth 服务器不是一个选项;使用此身份验证服务器是一项严格的业务要求。 auth 服务器有一堆我们想要授予访问权限的用户,但是对于我特定的 client_id none 用户具有与之关联的任何角色,我们希望避免通过 auth 添加角色服务器,因为这个过程……充其量是乏味的。官僚主义的繁文缛节,每次,对每个用户。我们的最终目标是在此服务器的数据库中拥有我们自己的角色,我们只去第 3 方处理登录,然后验证登录是否有效以及它是哪个用户。
如果我在 HttpMethodConstraint 中包含 rolesAllowed = { "debug" }
,将触发第 3 方身份验证服务器的身份验证并正常工作。但是因为 none 的用户具有与其关联的角色,所以他们没有所需的“调试”角色。 processRequest
方法永远不会到达,用户会收到“禁止”错误页面。
如果我删除或清空约束的 rolesAllowed
字段,则 不会 触发第 3 方身份验证服务器的身份验证,并且没有 UserPrincipal
我们可以用来识别用户。
我试过在请求到达我的 Servlet 之前放入 javax.servlet.Filter
来拦截请求,但是如果需要“调试”角色,那么过滤器也不会到达。我曾希望在用户通过身份验证后拦截请求,然后向用户添加角色,或者会话变量,或者我的 servlet 然后检查权限以执行各种操作的东西。
我已经尝试了一些没有触发身份验证的其他组合:
@ServletSecurity(httpMethodConstraints = { @HttpMethodConstraint(value = "GET", emptyRoleSemantic = ServletSecurity.EmptyRoleSemantic.PERMIT)})
和
@ServletSecurity(httpMethodConstraints = { @HttpMethodConstraint(value = "GET", transportGuarantee = ServletSecurity.TransportGuarantee.CONFIDENTIAL)})
运气不好。
有没有一种方法可以触发第 3 方身份验证,并获得具有经过身份验证的用户的 username/user ID 的 UserPrincipal,而无需特定角色? - 或 - 有没有一种方法可以在身份验证之后但在被 HttpMethodConstraint 阻止之前向经过身份验证的用户添加角色?
您的自定义过滤器方法不起作用的原因是 elytron 安全框架在您的过滤器链被调用之前处理得很好。您可以按照 here (Section 3.2.9) and here 的说明在 elytron 安全性中尝试自定义角色映射器以添加一些预定义的角色。
RoleMapper - After the roles have been decoded for an identity further
mapping can be applied, this could be as simple at normalising the
format of the names through to adding or removing specific role names.
您显然需要配置 elytron 子系统以使用您的自定义角色映射器。您可以查看 regex-role-mapper here 的示例配置(在您的情况下,您需要自定义 RoleMapper 而不是 regex-role-mapper)
我相信 elytrons 角色映射是可行的方法。您可以配置 Regex 映射器以将每个角色映射到一个静态角色。或者使用group-decoder-mapper将组名转换成角色
参见示例:https://wildfly-security.github.io/wildfly-elytron/blog/regex-role-mapper/
在本地 Wildfly 服务器上,我有一个简单的 Java servlet,如下所示:
import javax.servlet.annotation.HttpMethodConstraint;
import javax.servlet.annotation.ServletSecurity;
import javax.servlet.http.HttpServlet;
@ServletSecurity(httpMethodConstraints = { @HttpMethodConstraint(value = "GET", rolesAllowed = { "debug" })})
public class DebugServlet extends HttpServlet {
protected void processRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
try ( PrintWriter out = response.getWriter()) {
/* TODO output your page here. You may use following sample code. */
...
Principal user = request.getUserPrincipal();
out.println("<p>" + (user != null ? user.getName() : "No user") + "</p>");
...
}
}
}
我已经通过第三方身份验证服务器使用 OpenID Connect (OIDC) 设置了 Wildfly 的 Elytron v1.17.2 身份验证。如果重要的话,它是 而不是 Keycloak 服务器,更改 auth 服务器不是一个选项;使用此身份验证服务器是一项严格的业务要求。 auth 服务器有一堆我们想要授予访问权限的用户,但是对于我特定的 client_id none 用户具有与之关联的任何角色,我们希望避免通过 auth 添加角色服务器,因为这个过程……充其量是乏味的。官僚主义的繁文缛节,每次,对每个用户。我们的最终目标是在此服务器的数据库中拥有我们自己的角色,我们只去第 3 方处理登录,然后验证登录是否有效以及它是哪个用户。
如果我在 HttpMethodConstraint 中包含 rolesAllowed = { "debug" }
,将触发第 3 方身份验证服务器的身份验证并正常工作。但是因为 none 的用户具有与其关联的角色,所以他们没有所需的“调试”角色。 processRequest
方法永远不会到达,用户会收到“禁止”错误页面。
如果我删除或清空约束的 rolesAllowed
字段,则 不会 触发第 3 方身份验证服务器的身份验证,并且没有 UserPrincipal
我们可以用来识别用户。
我试过在请求到达我的 Servlet 之前放入 javax.servlet.Filter
来拦截请求,但是如果需要“调试”角色,那么过滤器也不会到达。我曾希望在用户通过身份验证后拦截请求,然后向用户添加角色,或者会话变量,或者我的 servlet 然后检查权限以执行各种操作的东西。
我已经尝试了一些没有触发身份验证的其他组合:
@ServletSecurity(httpMethodConstraints = { @HttpMethodConstraint(value = "GET", emptyRoleSemantic = ServletSecurity.EmptyRoleSemantic.PERMIT)})
和
@ServletSecurity(httpMethodConstraints = { @HttpMethodConstraint(value = "GET", transportGuarantee = ServletSecurity.TransportGuarantee.CONFIDENTIAL)})
运气不好。
有没有一种方法可以触发第 3 方身份验证,并获得具有经过身份验证的用户的 username/user ID 的 UserPrincipal,而无需特定角色? - 或 - 有没有一种方法可以在身份验证之后但在被 HttpMethodConstraint 阻止之前向经过身份验证的用户添加角色?
您的自定义过滤器方法不起作用的原因是 elytron 安全框架在您的过滤器链被调用之前处理得很好。您可以按照 here (Section 3.2.9) and here 的说明在 elytron 安全性中尝试自定义角色映射器以添加一些预定义的角色。
RoleMapper - After the roles have been decoded for an identity further mapping can be applied, this could be as simple at normalising the format of the names through to adding or removing specific role names.
您显然需要配置 elytron 子系统以使用您的自定义角色映射器。您可以查看 regex-role-mapper here 的示例配置(在您的情况下,您需要自定义 RoleMapper 而不是 regex-role-mapper)
我相信 elytrons 角色映射是可行的方法。您可以配置 Regex 映射器以将每个角色映射到一个静态角色。或者使用group-decoder-mapper将组名转换成角色
参见示例:https://wildfly-security.github.io/wildfly-elytron/blog/regex-role-mapper/