IllegalArgumentException: не найден обработчик для ключа 'javax.security.auth.Subject.container'
Я в основном слежу за этим учебником: https://www.ibm.com/developerworks/java/library/j-javaee8-security-api-4/index.html?ca=drs-
Моя среда разработки: TomEE 8.0 M1 Plume
pom.xml
<dependency>
<groupId>org.glassfish.soteria</groupId>
<artifactId>javax.security.enterprise</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>
ApplicationConfig:
@CustomFormAuthenticationMechanismDefinition(
loginToContinue = @LoginToContinue(
loginPage = "/login.xhtml",
errorPage = "/login.xhtml?error",
useForwardToLogin = true
)
)
@ApplicationScoped
@Named
public class ApplicationConfig {
}
TestServlet:
@WebServlet("/test")
public class TestServlet extends HttpServlet {
@Inject
SecurityContext securityContext;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
securityContext.isCallerInRole("admin");
}
}
Зайдите на http://localhost:8080/test, я получаю следующее исключение:
05-Dec-2018 16:38:39.132 SEVERE [http-nio-8080-exec-219] org.apache.catalina.core.StandardWrapperValve.invoke Servlet.service() for servlet [servlet.TestServlet] in context with path [] threw exception
java.lang.IllegalArgumentException: No handler can be found for the key 'javax.security.auth.Subject.container'
at javax.security.jacc.PolicyContext.getContext(PolicyContext.java:91)
at org.glassfish.soteria.authorization.JACC$2.run(JACC.java:175)
at java.security.AccessController.doPrivileged(Native Method)
at org.glassfish.soteria.authorization.JACC.getFromContext(JACC.java:173)
at org.glassfish.soteria.authorization.JACC.getSubject(JACC.java:73)
at org.glassfish.soteria.authorization.JACC.isCallerInRole(JACC.java:78)
at org.glassfish.soteria.authorization.spi.impl.ReflectionAndJaccCallerDetailsResolver.isCallerInRole(ReflectionAndJaccCallerDetailsResolver.java:82)
at org.glassfish.soteria.SecurityContextImpl.isCallerInRole(SecurityContextImpl.java:89)
at servlet.TestServlet.doGet(TestServlet.java:20)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:634)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:741)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.openejb.server.httpd.EEFilter.doFilter(EEFilter.java:65)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:199)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.tomee.catalina.OpenEJBValve.invoke(OpenEJBValve.java:44)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:607)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
at org.apache.tomee.catalina.OpenEJBSecurityListener$RequestCapturer.invoke(OpenEJBSecurityListener.java:97)
at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:668)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:770)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1415)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
Я из Spring и Spring Security, но плохо знаком с CDI и EJB.
Не могли бы вы сказать мне, как настроить это handler
или я что-то упустил?
Спасибо!
1 ответ
Ошибка вызвана тем, что TomEE не полностью реализует JACC, от которого зависит SPI авторизации по умолчанию ("ReflectionAndJaccCallerDetailsResolver") Soteria.
Обратите внимание, что TomEE фактически поддерживает JACC, но не полностью.
Здесь есть несколько вариантов (от простых до более сложных):
- Очевидное; дождитесь финала TomEE 8, который должен заставить это работать так или иначе (используя либо собственную реализацию EE Security, либо иным образом)
- Реализуйте SPI, который Soteria использует для авторизации, и вызовите собственные API-интерфейсы TomEE / Tomcat, чтобы сделать то же самое, что реализация по умолчанию теперь использует JACC.
- Внесите свой вклад в TomEE и внедрите недостающие биты в их реализацию JACC (или внесите вклад в Tomcat с реализацией только через Интернет). Для этого уже есть JIRA, см. TOMEE-1912
Я планировал предоставить пример для 2. и сделать SPI более очевидным в Soteria 1.1, но, к сожалению, пока не дошел до этого.