我已经设置了一个小型的maven web项目(JDK 1.8.0,源代码:1.8,JavaEE7)来测试Glassfish 4.1(build 13)中的JDBCRealm。它由两个实体组成:RealmUser和RealmGroup以及用于插入,更新和删除这些实体的JAX-RS服务。
我在glassfish-resources.xml中定义了JDBCResource,通过Glassfish管理控制台配置了域,并仅使用login-config(BASIC)设置web.xml。
使用 WebFilter 激活身份验证时,可以正常运行。
但是,当我在web.xml中设置安全约束时,每当我尝试访问受保护资源时,我都会收到以下异常(完整Stacktrace及以下详细信息) ):
Schwerwiegend: jdbcrealm.invaliduser
Fine: Cannot validate user
javax.security.auth.login.LoginException: Unable to connect to datasource java:app/jdbc/sampleresource for database user null.
...
Caused by: javax.naming.NamingException: Lookup failed for 'java:app/jdbc/sampleresource' in SerialContext[myEnv={com.sun.enterprise.connectors.jndisuffix=__nontx, java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is javax.naming.NamingException: Invocation exception: Got null ComponentInvocation ]
...
Caused by: javax.naming.NamingException: Invocation exception: Got null ComponentInvocation
...
非常感谢您的帮助!
我创建了一个Derby数据库(SampleDB,用户:testuser,密码:pw)并通过glassfish-resources.xml定义了一个JDBC资源:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions//EN" "http://glassfish.org/dtds/glassfish-resources_1_5.dtd">
<resources>
<jdbc-resource enabled="true" jndi-name="java:app/jdbc/sampleresource" object-type="user" pool-name="samplepool">
<description/>
</jdbc-resource>
<jdbc-connection-pool datasource-classname="org.apache.derby.jdbc.ClientDataSource40" name="samplepool" res-type="javax.sql.DataSource">
<property name="URL" value="jdbc:derby://localhost:1527/SampleDB"/>
<property name="serverName" value="localhost"/>
<property name="portNumber" value="1527"/>
<property name="databaseName" value="SampleDB"/>
<property name="User" value="testuser"/>
<property name="Password" value="pw"/>
<property name="driverClass" value="org.apache.derby.jdbc.ClientDriver"/>
</jdbc-connection-pool>
</resources>
我创建了persistence.xml,其中jta-data-source设置为 java:app / jdbc / sampleresource :
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="SampleRealmPU" transaction-type="JTA">
<jta-data-source>java:app/jdbc/sampleresource</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="javax.persistence.schema-generation.database.action" value="create"/>
</properties>
</persistence-unit>
</persistence>
在启动时,应用程序会添加默认用户(admin,pw)和默认组(Administrator),并将admin分配给Administrator组。
然后我使用管理控制台创建了JDBC领域,并将领域指向 java:app / jdbc / sampleresource 。
注意:
我实施了两项服务:
现在要激活访问组的身份验证,我创建了一个非常简单的web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>SampleRealm</realm-name>
</login-config>
</web-app>
和WebFilter:
@WebFilter("/webresources/UserService/groups/*")
public class Authenticator implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
if (req.authenticate(resp)) {
chain.doFilter(req, resp);
}
} catch (Throwable t) {
t.printStackTrace();
}
}
@Override
public void destroy() {
}
}
到目前为止一切正常!我必须提供默认用户凭据才能访问这些群组。
现在而不是使用Webfilter 我想使用 web.xml在组上定义相同的身份验证约束。我评论了整个WebFilter并修改了web.xml:
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<security-constraint>
<display-name>GroupConstraint</display-name>
<web-resource-collection>
<web-resource-name>UserService groups</web-resource-name>
<description/>
<url-pattern>/webresources/UserService/groups/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<description>requires auth</description>
<role-name>Administrator</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>SampleRealm</realm-name>
</login-config>
<security-role>
<description/>
<role-name>Administrator</role-name>
</security-role>
</web-app>
通过此设置,我可以访问用户资源(即数据库在那里)但是当我尝试访问组资源时,我得到 HTTP状态401 - 未经授权和Glassfish日志:
Fine: [Web-Security] Setting Policy Context ID: old = null ctxID = samples-realm-web/samples-realm-web
Fine: [Web-Security] hasUserDataPermission perm: ("javax.security.jacc.WebUserDataPermission" "/webresources/UserService/groups" "GET")
Fine: [Web-Security] hasUserDataPermission isGranted: true
Fine: [Web-Security] Policy Context ID was: samples-realm-web/samples-realm-web
Fine: [Web-Security] Generating a protection domain for Permission check.
Fine: [Web-Security] Codesource with Web URL: file:/samples-realm-web/samples-realm-web
Fine: [Web-Security] Checking Web Permission with Principals : null
Fine: [Web-Security] Web Permission = ("javax.security.jacc.WebResourcePermission" "/webresources/UserService/groups" "GET")
Finest: JACC Policy Provider: PolicyWrapper.implies, context (samples-realm-web/samples-realm-web)- result was(false) permission (("javax.security.jacc.WebResourcePermission" "/webresources/UserService/groups" "GET"))
Fine: [Web-Security] hasResource isGranted: false
Fine: [Web-Security] hasResource perm: ("javax.security.jacc.WebResourcePermission" "/webresources/UserService/groups" "GET")
Finest: Processing login with credentials of type: class com.sun.enterprise.security.auth.login.common.PasswordCredential
Fine: Logging in user [admin] into realm: SampleRealm using JAAS module: jdbcRealm
Fine: Login module initialized: class com.sun.enterprise.security.ee.auth.login.JDBCLoginModule
Schwerwiegend: jdbcrealm.invaliduser
Fine: Cannot validate user
javax.security.auth.login.LoginException: Unable to connect to datasource java:app/jdbc/sampleresource for database user null.
at com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm.getConnection(JDBCRealm.java:585)
at com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm.isUserValid(JDBCRealm.java:408)
at com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm.authenticate(JDBCRealm.java:324)
at com.sun.enterprise.security.ee.auth.login.JDBCLoginModule.authenticate(JDBCLoginModule.java:78)
at com.sun.enterprise.security.auth.login.PasswordLoginModule.authenticateUser(PasswordLoginModule.java:116)
at com.sun.enterprise.security.BasePasswordLoginModule.login(BasePasswordLoginModule.java:145)
at sun.reflect.GeneratedMethodAccessor52.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:755)
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:195)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:682)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:680)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:680)
at javax.security.auth.login.LoginContext.login(LoginContext.java:587)
at com.sun.enterprise.security.auth.login.LoginContextDriver.doPasswordLogin(LoginContextDriver.java:383)
at com.sun.enterprise.security.auth.login.LoginContextDriver.login(LoginContextDriver.java:241)
at com.sun.enterprise.security.auth.login.LoginContextDriver.login(LoginContextDriver.java:154)
at com.sun.web.security.RealmAdapter.authenticate(RealmAdapter.java:695)
at com.sun.web.security.RealmAdapter.authenticate(RealmAdapter.java:636)
at org.apache.catalina.authenticator.BasicAuthenticator.authenticate(BasicAuthenticator.java:166)
at com.sun.web.security.RealmAdapter.invokeAuthenticateDelegate(RealmAdapter.java:1524)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:606)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:702)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:415)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:282)
at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167)
at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:201)
at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:175)
at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:561)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545)
at java.lang.Thread.run(Thread.java:744)
Caused by: javax.naming.NamingException: Lookup failed for 'java:app/jdbc/sampleresource' in SerialContext[myEnv={com.sun.enterprise.connectors.jndisuffix=__nontx, java.naming.factory.initial=com.sun.enterprise.naming.impl.SerialInitContextFactory, java.naming.factory.state=com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl, java.naming.factory.url.pkgs=com.sun.enterprise.naming} [Root exception is javax.naming.NamingException: Invocation exception: Got null ComponentInvocation ]
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:491)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:438)
at javax.naming.InitialContext.lookup(InitialContext.java:417)
at javax.naming.InitialContext.lookup(InitialContext.java:417)
at org.glassfish.resourcebase.resources.naming.ResourceNamingService.lookup(ResourceNamingService.java:236)
at com.sun.enterprise.connectors.service.ConnectorResourceAdminServiceImpl.lookup(ConnectorResourceAdminServiceImpl.java:224)
at com.sun.enterprise.connectors.ConnectorRuntime.lookupNonTxResource(ConnectorRuntime.java:553)
at com.sun.enterprise.connectors.ConnectorRuntime.lookupNonTxResource(ConnectorRuntime.java:538)
at com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm.getConnection(JDBCRealm.java:573)
... 48 more
Caused by: javax.naming.NamingException: Invocation exception: Got null ComponentInvocation
at com.sun.enterprise.naming.impl.GlassfishNamingManagerImpl.getComponentId(GlassfishNamingManagerImpl.java:842)
at com.sun.enterprise.naming.impl.GlassfishNamingManagerImpl.lookup(GlassfishNamingManagerImpl.java:714)
at com.sun.enterprise.naming.impl.JavaURLContext.lookup(JavaURLContext.java:167)
at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:471)
... 56 more
Fine: JAAS authentication aborted.
Finest: doPasswordLogin fails
javax.security.auth.login.LoginException: Security Exception
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:840)
at javax.security.auth.login.LoginContext.access$000(LoginContext.java:195)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:682)
at javax.security.auth.login.LoginContext$4.run(LoginContext.java:680)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.login.LoginContext.invokePriv(LoginContext.java:680)
at javax.security.auth.login.LoginContext.login(LoginContext.java:587)
at com.sun.enterprise.security.auth.login.LoginContextDriver.doPasswordLogin(LoginContextDriver.java:383)
at com.sun.enterprise.security.auth.login.LoginContextDriver.login(LoginContextDriver.java:241)
at com.sun.enterprise.security.auth.login.LoginContextDriver.login(LoginContextDriver.java:154)
at com.sun.web.security.RealmAdapter.authenticate(RealmAdapter.java:695)
at com.sun.web.security.RealmAdapter.authenticate(RealmAdapter.java:636)
at org.apache.catalina.authenticator.BasicAuthenticator.authenticate(BasicAuthenticator.java:166)
at com.sun.web.security.RealmAdapter.invokeAuthenticateDelegate(RealmAdapter.java:1524)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:606)
at org.apache.catalina.core.StandardPipeline.doInvoke(StandardPipeline.java:702)
at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:673)
at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:99)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:174)
at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:415)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:282)
at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:459)
at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:167)
at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:201)
at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:175)
at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
at org.glassfish.grizzly.filterchain.ExecutorResolver$9.execute(ExecutorResolver.java:119)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:561)
at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access$100(WorkerThreadIOStrategy.java:56)
at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:565)
at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:545)
at java.lang.Thread.run(Thread.java:744)
Caused by: java.lang.SecurityException
at javax.security.auth.login.LoginContext.invoke(LoginContext.java:841)
... 39 more
Warnung: WEB9102: Web Login Failed: com.sun.enterprise.security.auth.login.common.LoginException: Login failed: Security Exception
我尝试了几件事来解决这个问题,包括:
使用glassfish-web.xml的RoleMappings示例:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE glassfish-web-app PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Servlet 3.0//EN" "http://glassfish.org/dtds/glassfish-web-app_3_0-1.dtd">
<glassfish-web-app error-url="" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMSSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/h2ee web-app_2_4.xsd">
<security-role-mapping>
<role-name>Administrator</role-name>
<group-name>Administrator</group-name>
</security-role-mapping>
</glassfish-web-app>
非常感谢您的帮助!
答案 0 :(得分:0)
您的密码加密设置为SHA-256 ...将其设为AES
使用SHA-256作为摘要Algo而不是加密...尝试使用Hex作为编码