如何在Keycloak和Apache Deltaspike中重定向到登录页面?

问题描述 投票:0回答:1

我正在使用Java EE Web应用程序,它将利用Keycloak作为身份和身份验证提供程序。此外,出于各种目的,我正在项目中使用Apache DeltaSpike。我想利用DeltaSpike的security module来注释一些方法,这些方法指示用户必须登录才能访问它们。如果此检查失败,我想将用户自动重定向到Keycloak登录页面。但是,我还没有找到一种方法来完成此任务。

相关的y web.xml文件如下所示,表明我已将Keycloak配置为我的应用程序的安全性机制:

<login-config>
    <auth-method>KEYCLOAK</auth-method>
    <realm-name>KEYCLOAK</realm-name>
</login-config>

我已经实现了相应的AccessDecisionVoter,如下所示:

public class LoginRequiredAccessDecisionVoter extends AbstractAccessDecisionVoter {

    @Inject
    private KeycloakSecurityContext securityContext = null;

    /*
     * (non-Javadoc)
     *
     * @see
     * org.apache.deltaspike.security.api.authorization.AbstractAccessDecisionVoter#
     * checkPermission(org.apache.deltaspike.security.api.authorization.
     * AccessDecisionVoterContext, java.util.Set)
     */
    @Override
    protected void checkPermission(AccessDecisionVoterContext accessDecisionVoterContext,
            Set<SecurityViolation> violations) {
        if (securityContext == null) {
            violations.add(new LoginRequiredSecurityViolation());
        }
    }

}

然后,我将DeltaSpike的type-aware JSF navigation配置为使用此类进行保护。我用浏览器访问了受保护的资源,并看到触发了我的AccessDecisionVoter。我看到调用了checkPermission方法,并抛出了ErrorViewAwareAccessDeniedException。因此,我实现了一个ExceptionHandler来捕获异常并将用户重定向到Keycloak登录页面。看起来像这样:

@ExceptionHandler
public class SecurityExceptionHandler {

    @Inject
    private HttpServletRequest servletRequest = null;

    @Inject
    @DeltaSpike
    private HttpServletResponse servletResponse = null;

    /**
     * Handles {@link ErrorViewAwareAccessDeniedException} exceptions
     * 
     * @param event The exception event
     */
    public void handleErrorViewAwareAccessDeniedException(
            @Handles ExceptionEvent<ErrorViewAwareAccessDeniedException> event) {
        Set<SecurityViolation> violations = event.getException().getViolations();
        for (SecurityViolation v : violations) {
            if (v instanceof LoginRequiredSecurityViolation) {
                try {
                    this.servletRequest.authenticate(this.servletResponse);
                    event.handled();
                } catch (IOException | ServletException e) {
                }
            }
        }
    }
}

我以为servletRequest.authenticate()呼叫将启动重定向到Keycloak登录页面的重定向。但是,事实并非如此。相反,我抛出了ServletException / NullPointerException

是否有更好的方法以编程方式将用户重定向到Keycloak?是否有异常或可以引发触发重定向的东西?有什么想法吗?

security jsf java-ee keycloak deltaspike
1个回答
0
投票

如果我尝试创建ExceptionHandler并在注入的authenticate()上调用servletRequest,则会收到以下异常:

java.lang.IllegalStateException: Attempt to access the request/response without an active HTTP request
    org.apache.deltaspike.servlet.impl.produce.RequestResponseHolder.get(RequestResponseHolder.java:105)
    org.apache.deltaspike.servlet.impl.produce.ServletObjectProducer.getHttpServletResponse(ServletObjectProducer.java:95)
    sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    java.lang.reflect.Method.invoke(Method.java:498)
    org.apache.webbeans.inject.InjectableMethod.doInjection(InjectableMethod.java:155)
    org.apache.webbeans.portable.ProducerMethodProducer.produce(ProducerMethodProducer.java:89)
    org.apache.webbeans.portable.AbstractProducer.produce(AbstractProducer.java:134)
    org.apache.webbeans.component.AbstractOwbBean.create(AbstractOwbBean.java:122)
    org.apache.webbeans.component.ProducerMethodBean.create(ProducerMethodBean.java:95)
    org.apache.webbeans.context.creational.BeanInstanceBag.create(BeanInstanceBag.java:76)
    org.apache.webbeans.context.AbstractContext.getInstance(AbstractContext.java:159)
    org.apache.webbeans.context.AbstractContext.get(AbstractContext.java:125)
    org.apache.webbeans.intercept.NormalScopedBeanInterceptorHandler.getContextualInstance(NormalScopedBeanInterceptorHandler.java:101)
    org.apache.webbeans.intercept.RequestScopedBeanInterceptorHandler.getContextualInstance(RequestScopedBeanInterceptorHandler.java:76)
    org.apache.webbeans.intercept.NormalScopedBeanInterceptorHandler.get(NormalScopedBeanInterceptorHandler.java:71)
    org.apache.webbeans.custom.servlet.http.HttpServletResponse$$OwbNormalScopeProxy0.isCommitted(javax/servlet/http/HttpServletResponse.java)
    org.apache.catalina.connector.Request.authenticate(Request.java:2742)
    org.apache.catalina.connector.RequestFacade.authenticate(RequestFacade.java:1081)
    org.apache.webbeans.custom.servlet.http.HttpServletRequest$$OwbNormalScopeProxy0.authenticate(javax/servlet/http/HttpServletRequest.java)

[从request提取response / facesContext对象时,我没有得到此异常:

FacesContext ctx = FacesContext.getCurrentInstance();
ExternalContext eCtx = ctx.getExternalContext();
HttpServletResponse response = (HttpServletResponse) eCtx.getResponse();
HttpServletRequest request = (HttpServletRequest) eCtx.getRequest();
request.authenticate(response);

我不太熟悉deltaspike,也没有在测试中添加密钥斗篷。

© www.soinside.com 2019 - 2024. All rights reserved.