如何在 JSF 上下文中替换经过身份验证的 javax.security.Principal?

How to replace the authenticated javax.security.Principal in JSF context?

我想在我的 JSF 应用程序中创建一个 "Impersonate" 功能。此功能将使管理员能够在不知道密码的情况下访问通过低级别用户身份验证的应用程序。

虽然这会很简单 setUserPrincipal,类似于我用来获取当前登录用户的方法 FacesContext.getCurrentInstance().getExternalContext().getUserPrincipal(),但我在 javax.faces.context.ExternalContext...

中找不到任何 "setUserPrincipal" 方法

简而言之,我想要的是以编程方式更改当前登录的用户,这样管理员就可以在不通知凭据的情况下模拟任何其他用户。可能吗?

谢谢

我强烈建议不要玩 authentication/authorization 除非你真的没有其他选择。

无论如何,不​​要考虑 JSF,它出现得太晚了。

最简单的方法是提供带有过滤器的自定义请求:

@WebFilter(filterName = "impersonateFilter", urlPatterns = "/*", asyncSupported = true)
public class ImpersonateFilter implements Filter
{
    @Override
    public void init(FilterConfig filterConfig) throws ServletException
    {
        // do nothing
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException
    {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        ImpersonateRequest impersonateRequest = new ImpersonateRequest(httpRequest);
        chain.doFilter(impersonateRequest, response);
    }

    @Override
    public void destroy()
    {
        // do nothing
    }

    public static class ImpersonateRequest extends HttpServletRequestWrapper
    {
        protected Principal principal;

        public ImpersonateRequest(HttpServletRequest request)
        {
            super(request);

            HttpSession session = request.getSession(false);
            if(session != null)
            {
                principal = (Principal) session.getAttribute(ImpersonateRequest.class.getName());
            }
        }

        @Override
        public Principal getUserPrincipal()
        {
            if(principal == null)
            {
                principal = super.getUserPrincipal();
            }

            return principal;
        }

        public void setUserPrincipal(Principal principal)
        {
            this.principal = principal;
            getSession().setAttribute(ImpersonateRequest.class.getName(), principal);
        }

        @Override
        public String getRemoteUser()
        {
            return principal == null ? super.getRemoteUser() : principal.getName();
        }
    }
}

像这样应该就足够了。