java - Glassfish 3 安全性 - 使用 JDBC 领域的基于表单的身份验证

标签 java security jsf jakarta-ee glassfish

我想通过 glassfishV3 了解基于表单的安全性和 JDBC 领域,因此我决定创建一个仅允许登录和注销的小应用程序,我按照此 book 中的说明进行操作这样做。

我了解保持装置的工作原理,但出了点问题,我无法使其正常工作。

我首先做的是创建一个带有 JPA 注释的小数据库:

@Entity
@Table(name="USERS")
public class User implements Serializable {

    private static final long serialVersionUID = -1244856316278032177L;
    @Id
    @GeneratedValue
    @Column(nullable = false)
    private Long id;
    @Column(nullable = false)
    private String email;
    @Column(nullable = false)
    private String password;
    @OneToMany(mappedBy = "user")
    private List<Group> groups;
    //GET & SET METHODS...

}

这里是保存每个用户角色的另一个表
@Entity
@Table(name="GROUPS")
public class Group implements Serializable {

    private static final long serialVersionUID = -7274308564659753174L;
    @Id
    @GeneratedValue
    @Column(nullable = false)
    private Long id;
    @Column(nullable = false)
    private String groupName;
    @ManyToOne
    @JoinColumn(name = "USERS_ID", nullable = false)
    private User user;
    //GET & SET METHODS...
    }

当数据库准备好时,我手动添加了一些数据

enter image description here

下一步是配置安全领域。

enter image description here

然后将安全配置添加到我的 web.xml 文件
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    version="3.0">

    <display-name>CHAPTER x 12 Container Managed Authentication and
        Authorization</display-name>
    <welcome-file-list>
        <welcome-file>index.xhtml</welcome-file>
    </welcome-file-list>
    <servlet>
        <servlet-name>Faces Servlet</servlet-name>
        <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <servlet-mapping>
        <servlet-name>Faces Servlet</servlet-name>
        <url-pattern>*.xhtml</url-pattern>
    </servlet-mapping>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>VISITOR PERMISIONS</web-resource-name>           
            <url-pattern>/index.xhtml</url-pattern>         
            <url-pattern>/visitorpanel.xhtml</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
        </web-resource-collection>
        <auth-constraint>
            <role-name>visitors</role-name>
            <role-name>users</role-name>
            <role-name>administrators</role-name>
        </auth-constraint>
    </security-constraint>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>USERS PERMISIONS</web-resource-name>         
            <url-pattern>/userpanel.xhtml</url-pattern>
            <url-pattern>/index.xhtml</url-pattern>         
            <url-pattern>/visitorpanel.xhtml</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>         
        </web-resource-collection>
        <auth-constraint>           
            <role-name>users</role-name>
            <role-name>administrators</role-name>
        </auth-constraint>
    </security-constraint>

    <security-constraint>
        <web-resource-collection>
            <web-resource-name>ADMIN PERMISIONS</web-resource-name>             
            <url-pattern>/adminpanel.xhtml</url-pattern>
            <url-pattern>/userpanel.xhtml</url-pattern>
            <url-pattern>/index.xhtml</url-pattern>         
            <url-pattern>/visitorpanel.xhtml</url-pattern>          
            <http-method>GET</http-method>
            <http-method>POST</http-method>
        </web-resource-collection>
        <auth-constraint>           
            <role-name>administrators</role-name>
        </auth-constraint>
    </security-constraint>

    <login-config>
        <auth-method>FORM</auth-method>
        <realm-name>DBRealm</realm-name>
        <form-login-config>
            <form-login-page>/index.xhtml</form-login-page>
            <form-error-page>/error.xhtml</form-error-page>
        </form-login-config>
    </login-config>

    <security-role>
    <role-name>visitors</role-name>
    </security-role>

    <security-role>
    <role-name>users</role-name>
    </security-role>

    <security-role>
    <role-name>administrators</role-name>
    </security-role>
</web-app>

我在这里的目标是:
  • 管理员可以查看所有页面
  • 访问者只能看到 index.xhtml 和visitorpanel.xhtml
  • 用户可以看到 index.xhtml、visitorpanel.xhtml 和 userpanel.xhtml

  • 我认为配置是正确的。

    最后一步是在 index.xhtml 页面中创建登录表单:
    <form method="post" action="j_security_check" name="loginForm">
    
            <h:outputLabel id="userNameLabel" for="j_username" value="Enter your em@il:"/>
            <h:inputText id="j_username" autocomplete="off" />
            <br/>
            <h:outputLabel id="passwordLabel" for="j_password" value="Enter your em@il password:"/>
            <h:inputSecret id="j_password" autocomplete="off"/>
            <br/>
            <h:commandButton type="submit" value="Login"/>
            <h:commandButton type="reset" value="Clear"/>
      </form>
    

    该程序构建良好,但我有以下问题:

    1- 当我尝试以用户或管理员身份登录时(访问者不需要登录),我被重定向到 error.xhtml 页面,并且在控制台中我看到一个异常:

    SEVERE: SEC1112: Cannot validate user [admin@gmail.com] for JDBC realm. WARNING: Web login failed: Login failed: javax.security.auth.login.LoginException: Security Exception WARNING: PWC4011: Unable to set request character encoding to UTF-8 from context /CHAPTER_12_x_Container_Managed_Authentication_and_Authorization, because request parameters have already been read, or ServletRequest.getReader() has already been called



    2- 当我尝试通过 URL 导航到某些页面时,没有任何 react 。我觉得没问题,但是当我尝试访问visitorpanel.xhtml时,它应该让我,因为不需要登录就可以看到它。
    如果想让每个人都看到它,我是否需要从安全配置中删除该页面?

    3- 我也很好奇为什么我在实现登录时不能使用标签 h:form 而不仅仅是表单?

    我真的很感谢一些帮助,我花了几个小时阅读本书的第一章并尝试实现我自己的示例,但我被卡住了。我想我已经接近解决方案了。

    更新

    我将默认主体更改为访问者用户名。但它仍然不起作用

    enter image description here

    我还在 Realm 配置中添加了更多选项

    enter image description here

    但是当我尝试登录时,我仍然看到一个异常,上面写着:

    SEVERE: SEC1112: Cannot validate user [admin@gmail.com] for JDBC realm. WARNING: Web login failed: Login failed: javax.security.auth.login.LoginException: Security Exception WARNING: PWC4011: Unable to set request character encoding to UTF-8 from context /CHAPTER_12_x_Container_Managed_Authentication_and_Authorization, because request parameters have already been read, or ServletRequest.getReader() has already been called



    我仍然不知道缺少什么。

    - 会不会是表名不能大写?

    - 列名不应该是大写吗?

    - 会不会是表创建错误?

    - 难道我不能使用 PASSWORD 作为列名,因为它会产生某种冲突吗?

    我真的不明白为什么会有这个异常(exception)。我从管理面板 ping 数据库,一切似乎都是正确的。

    有人可以帮我弄清楚这个吗?

    更新 2

    我将“javax.enterprise.system.core.security”日志记录选项更改为 FINE 级别,以便在发生异常时获得更多信息,这是我尝试登录时的结果:

    FINE: Intercept Entry: intercept: SOAP defaultServerID: null defaultClientID: null FINE: ID Entry: module class: com.sun.xml.wss.provider.ClientSecurityAuthModule id: XWS_ClientProvider type: client request policy: javax.security.auth.message.MessagePolicy@e95a72 response policy: javax.security.auth.message.MessagePolicy@310a6d options: {signature.key.alias=s1as, debug=false, dynamic.username.password=false, encryption.key.alias=s1as} FINE: ID Entry: module class: com.sun.xml.wss.provider.ClientSecurityAuthModule id: ClientProvider type: client request policy: javax.security.auth.message.MessagePolicy@1829770 response policy: javax.security.auth.message.MessagePolicy@a4461e options: {signature.key.alias=s1as, debug=false, dynamic.username.password=false, encryption.key.alias=s1as, security.config=C:\jeeAplicationServer\glassfishv3\glassfish\domains\domain1/config/wss-server-config-1.0.xml} FINE: ID Entry: module class: com.sun.xml.wss.provider.ServerSecurityAuthModule id: XWS_ServerProvider type: server request policy: javax.security.auth.message.MessagePolicy@f79c86 response policy: javax.security.auth.message.MessagePolicy@454bf7 options: {signature.key.alias=s1as, debug=false, encryption.key.alias=s1as} FINE: ID Entry: module class: com.sun.xml.wss.provider.ServerSecurityAuthModule id: ServerProvider type: server request policy: javax.security.auth.message.MessagePolicy@17e85e4 response policy: javax.security.auth.message.MessagePolicy@1887906 options: {signature.key.alias=s1as, debug=false, encryption.key.alias=s1as, security.config=C:\jeeAplicationServer\glassfishv3\glassfish\domains\domain1/config/wss-server-config-1.0.xml} FINE: [Web-Security] Setting Policy Context ID: old = null ctxID = CHAPTER_x_12_Container_Managed_Authentication_and_Authorization/CHAPTER_x_12_Container_Managed_Authentication_and_Authorization FINE: [Web-Security] hasUserDataPermission perm: (javax.security.jacc.WebUserDataPermission /j_security_check POST) FINE: [Web-Security] hasUserDataPermission isGranted: true FINE: Logging in user [admin@gmail.com] into realm: DBRealm using JAAS module: jdbcRealm FINE: Login module initialized: class com.sun.enterprise.security.auth.login.JDBCLoginModule SEVERE: SEC1112: Cannot validate user [admin@gmail.com] for JDBC realm. FINE: Cannot validate user javax.security.auth.login.LoginException: Unable to connect to datasource jdbc/security for database user user. at com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm.getConnection(JDBCRealm.java:550) at com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm.isUserValid(JDBCRealm.java:393) at com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm.authenticate(JDBCRealm.java:311) at com.sun.enterprise.security.auth.login.JDBCLoginModule.authenticate(JDBCLoginModule.java:72) at com.sun.enterprise.security.auth.login.PasswordLoginModule.authenticateUser(PasswordLoginModule.java:90) at com.sun.appserv.security.AppservPasswordLoginModule.login(AppservPasswordLoginModule.java:141) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at javax.security.auth.login.LoginContext.invoke(LoginContext.java:769) at javax.security.auth.login.LoginContext.access$000(LoginContext.java:186) at javax.security.auth.login.LoginContext$4.run(LoginContext.java:683) 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:579) at com.sun.enterprise.security.auth.login.LoginContextDriver.doPasswordLogin(LoginContextDriver.java:341) at com.sun.enterprise.security.auth.login.LoginContextDriver.login(LoginContextDriver.java:199) at com.sun.enterprise.security.auth.login.LoginContextDriver.login(LoginContextDriver.java:152) at com.sun.web.security.RealmAdapter.authenticate(RealmAdapter.java:479) at com.sun.web.security.RealmAdapter.authenticate(RealmAdapter.java:418) at org.apache.catalina.authenticator.FormAuthenticator.authenticate(FormAuthenticator.java:264) at org.apache.catalina.authenticator.AuthenticatorBase.processSecurityCheck(AuthenticatorBase.java:1015) at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:614) at org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:615) at com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97) at com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185) at org.apache.catalina.connector.CoyoteAdapter.doService(CoyoteAdapter.java:325) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:226) at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165) at com.sun.grizzly.http.ProcessorTask.invokeAdapter(ProcessorTask.java:791) at com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693) at com.sun.grizzly.http.ProcessorTask.process(ProcessorTask.java:954) at com.sun.grizzly.http.DefaultProtocolFilter.execute(DefaultProtocolFilter.java:170) at com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter(DefaultProtocolChain.java:135) at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:102) at com.sun.grizzly.DefaultProtocolChain.execute(DefaultProtocolChain.java:88) at com.sun.grizzly.http.HttpProtocolChain.execute(HttpProtocolChain.java:76) at com.sun.grizzly.ProtocolChainContextTask.doCall(ProtocolChainContextTask.java:53) at com.sun.grizzly.SelectionKeyContextTask.call(SelectionKeyContextTask.java:57) at com.sun.grizzly.ContextTask.run(ContextTask.java:69) at com.sun.grizzly.util.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:330) at com.sun.grizzly.util.AbstractThreadPool$Worker.run(AbstractThreadPool.java:309) at java.lang.Thread.run(Thread.java:662) Caused by: javax.naming.NamingException: Lookup failed for 'jdbc/security' in SerialContext [Root exception is javax.naming.NameNotFoundException: security not found] at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:442) at javax.naming.InitialContext.lookup(InitialContext.java:392) at javax.naming.InitialContext.lookup(InitialContext.java:392) at com.sun.enterprise.connectors.service.ConnectorResourceAdminServiceImpl.lookup(ConnectorResourceAdminServiceImpl.java:203) at com.sun.enterprise.connectors.ConnectorRuntime.lookupNonTxResource(ConnectorRuntime.java:440) at com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm.getConnection(JDBCRealm.java:538) ... 44 more Caused by: javax.naming.NameNotFoundException: security not found at com.sun.enterprise.naming.impl.TransientContext.doLookup(TransientContext.java:197) at com.sun.enterprise.naming.impl.TransientContext.lookup(TransientContext.java:168) at com.sun.enterprise.naming.impl.TransientContext.lookup(TransientContext.java:172) at com.sun.enterprise.naming.impl.SerialContextProviderImpl.lookup(SerialContextProviderImpl.java:58) at com.sun.enterprise.naming.impl.LocalSerialContextProviderImpl.lookup(LocalSerialContextProviderImpl.java:101) at com.sun.enterprise.naming.impl.SerialContext.lookup(SerialContext.java:430) ... 49 more

    FINE: JAAS authentication aborted. WARNING: Web login failed: Login failed: javax.security.auth.login.LoginException: Security Exception FINE: [Web-Security] Policy Context ID was: CHAPTER_x_12_Container_Managed_Authentication_and_Authorization/CHAPTER_x_12_Container_Managed_Authentication_and_Authorization FINE: [Web-Security] hasUserDataPermission perm: (javax.security.jacc.WebUserDataPermission /error.xhtml GET) FINE: [Web-Security] hasUserDataPermission isGranted: true



    更新 3

    也许连接池有问题。
    这是我的连接池的样子:

    enter image description here

    enter image description here

    enter image description here

    我没有太多属性,也许缺少某些东西?

    现在我还创建了一个 JDBC 资源,如下所示:

    enter image description here

    (Realm 中的 JNDI 名称,改为 jdbc/studydb)

    我的persistence.xml 看起来像这样:
    <?xml version="1.0" encoding="UTF-8"?>
    <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
        <persistence-unit name="CHAPTER x 12 Container Managed Authentication and Authorization">
            <jta-data-source>jdbc/studydb</jta-data-source>     
            <class>entities.User</class>
            <class>entities.Group</class>
        </persistence-unit>
    </persistence>
    

    我想我取得了一些进展,现在我看到的异常(exception)是:
    > SEVERE: jdbcrealm.invaliduserreason
    >      FINE: Cannot validate user
    >      java.sql.SQLSyntaxErrorException: Schema 'ADMIN' does not exist
    >       at org.apache.derby.client.am.SQLExceptionFactory40.getSQLException(Unknown
    > Source)
    >      ....
    >      
    >      Caused by: org.apache.derby.client.am.SqlException: Schema 'ADMIN' does not exist
    >       at org.apache.derby.client.am.Statement.completeSqlca(Unknown Source)
    >      ...
    >      FINE: JAAS authentication aborted.
    >      WARNING: Web login failed: Login failed: javax.security.auth.login.LoginException: Security Exception
    >      FINE: [Web-Security] Policy Context ID was: CHAPTER_x_12_Container_Managed_Authentication_and_Authorization/CHAPTER_x_12_Container_Managed_Authentication_and_Authorization
    >      FINE: [Web-Security] hasUserDataPermission perm: (javax.security.jacc.WebUserDataPermission /error.xhtml GET)
    >      FINE: [Web-Security] hasUserDataPermission isGranted: true
    >      WARNING: PWC4011: Unable to set request character encoding to UTF-8 from context 
    > /CHAPTER_12_x_Container_Managed_Authentication_and_Authorization, 
    > because request parameters have already been read, or 
    > ServletRequest.getReader() has already been called
    

    更新 4

    我更改了数据库,它的组织有误,所以我对我的实体进行了一些更改:
    @Entity
        @Table(name="USERS", schema="ADMIN")
        public class User implements Serializable {
    
            private static final long serialVersionUID = -1244856316278032177L;
            @Id 
            @Column(nullable = false)
            private String userid;  
    
            @Column(nullable = false)
            private String password;
    
            @ManyToOne
            @JoinTable(name="USER_GROUP",schema="ADMIN", joinColumns = @JoinColumn(name="userid", referencedColumnName="userid"), inverseJoinColumns=@JoinColumn(name="groupid", referencedColumnName= "groupid") )
            private Group group;
            //GET & SET METHODS
    

    @实体
    @Table(name="GROUPS", schema="ADMIN")
    公共(public)类组实现可序列化{
    private static final long serialVersionUID = -7274308564659753174L;
    @Id
    @Column(nullable = false)
    private String groupid;
    
    @OneToMany(mappedBy="group")
    private Set<User> users;
    

    //获取和设置方法

    所以我还必须编辑 DBRealm,现在它看起来像这样:

    enter image description here

    但是当我登录时,我再次遇到异常:
    FINE: [Web-Security] Policy Context ID was: CHAPTER_x_12_Container_Managed_Authentication_and_Authorization/CHAPTER_x_12_Container_Managed_Authentication_and_Authorization
    FINE: [Web-Security] hasUserDataPermission perm: (javax.security.jacc.WebUserDataPermission /j_security_check POST)
    FINE: [Web-Security] hasUserDataPermission isGranted: true
    FINE: Logging in user [user@gmail.com] into realm: DBRealm using JAAS module: jdbcRealm
    FINE: Login module initialized: class com.sun.enterprise.security.auth.login.JDBCLoginModule
    SEVERE: SEC1111: Cannot load group for JDBC realm user [user@gmail.com].
    FINE: Cannot load group
    java.sql.SQLSyntaxErrorException: Column 'USERID' is either not in any table in the FROM list or appears within a join specification and is outside the scope of the join specification or appears in a HAVING clause and is not in the GROUP BY list. If this is a CREATE or ALTER TABLE  statement then 'USERID' is not a column in the target table.
    ....
    ....
    Caused by: org.apache.derby.client.am.SqlException: Column 'USERID' is either not in any table in the FROM list or appears within a join specification and is outside the scope of the join specification or appears in a HAVING clause and is not in the GROUP BY list. If this is a CREATE or ALTER TABLE  statement then 'USERID' is not a column in the target table.
        at org.apache.derby.client.am.Statement.completeSqlca(Unknown Source)
    ....
    ....
    FINE: JAAS login complete.
    FINE: JAAS authentication committed.
    FINE: Password login succeeded for : user@gmail.com
    FINE: permission check done to set SecurityContext
    FINE: Set security context as user: user@gmail.com
    FINE: [Web-Security] Policy Context ID was: CHAPTER_x_12_Container_Managed_Authentication_and_Authorization/CHAPTER_x_12_Container_Managed_Authentication_and_Authorization
    FINE: [Web-Security] hasUserDataPermission perm: (javax.security.jacc.WebUserDataPermission  GET)
    FINE: [Web-Security] hasUserDataPermission isGranted: true
    FINE: permission check done to set SecurityContext
    FINE: SecurityContext: setCurrentSecurityContext method called
    
    FINE: [Web-Security] Policy Context ID was: CHAPTER_x_12_Container_Managed_Authentication_and_Authorization/CHAPTER_x_12_Container_Managed_Authentication_and_Authorization
    FINE: [Web-Security] hasUserDataPermission perm: (javax.security.jacc.WebUserDataPermission /adminpanel.xhtml GET)
    FINE: [Web-Security] hasUserDataPermission isGranted: true
    FINE: [Web-Security] Policy Context ID was: CHAPTER_x_12_Container_Managed_Authentication_and_Authorization/CHAPTER_x_12_Container_Managed_Authentication_and_Authorization
    FINE: [Web-Security] Generating a protection domain for Permission check.
    FINE: [Web-Security] Checking with Principal : user@gmail.com
    FINE: [Web-Security] Checking with Principal : visitors
    FINE: [Web-Security] Checking with Principal : users
    FINE: [Web-Security] Checking with Principal : administrators
    FINE: [Web-Security] Codesource with Web URL: file:/CHAPTER_x_12_Container_Managed_Authentication_and_Authorization/CHAPTER_x_12_Container_Managed_Authentication_and_Authorization
    FINE: [Web-Security] Checking Web Permission with Principals : user@gmail.com, visitors, users, administrators
    FINE: [Web-Security] Web Permission = (javax.security.jacc.WebResourcePermission /adminpanel.xhtml GET)
    FINE: [Web-Security] hasResource isGranted: true
    FINE: [Web-Security] hasResource perm: (javax.security.jacc.WebResourcePermission /adminpanel.xhtml GET)
    FINE: SecurityContext: setCurrentSecurityContext method called
    
    WARNING: Resource not found: com/sun/enterprise/v3/admin/adapter/theme/com/sun/webui/jsf/suntheme/images/masthead/masthead_button_over.gif
    

    最佳答案

    您的配置中缺少一些位:

  • 密码以明文形式存储在数据库中。这很可能是不正确的。 Glassfish 3.1 默认使用 SHA-256 算法,因此 JDBC 领域将无法对用户进行身份验证,因为数据库中存储的值与领域创建的摘要不匹配。您需要在领域配置中指定显式摘要算法,或依赖默认值。此外,您需要确保您的应用程序在创建新用户或修改他/她的密码时创建摘要。如果要以明文形式存储密码,则必须为摘要算法指定“none”值。
  • 仅指定摘要算法是不够的。您需要指定存储摘要的编码(因为,摘要只是一个字节序列,可能不会存储为纯 ASCII 序列)。 Glassfish 支持 Hex 和 Base64 编码,并且默认使用 Hex 编码。 Your app should therefore apply the same encoding在领域中配置,在存储密码摘要之前。请注意,当您指定“none”摘要算法以纯文本存储密码时,您无需对存储的密码进行编码(同样,您也无需指定编码);至少这是我从阅读 Glassfish 来源中观察到的。
  • 此外,用户组映射目前似乎是 1:1。 You might want to use a separate join table允许组和用户之间的 1:N 映射。
  • 您还需要确保启用“默认主体到角色映射”选项。如果没有此选项,您将需要手动 map the roles in web.xml to users and groups in your realm .

  • 关于使用的话题form而不是 h:form ,根本原因是 JSF 运行时不允许您指定 action h:form 的属性标签。该值由 JSF 运行时在编码响应时设置,因此,您将无法指定 j_security_check 的值。当您使用 h:form标签。 The documentation states this quite explicitly :

    The value of the "action" attribute must be the result of passing the view identifier of the current view to the getActionURL() method of the ViewHandler for this application, then passing that String to the encodeActionURL() method on the ExternalContext.



    更新

    根据发布的堆栈跟踪,我可以推断 Realm 使用的 JNDI 数据源(在 JNDI 字段中指定)在 Glassfish 域中不可用。 JDBC 领域的先决条件之一是在 Glassfish 域配置中注册了一个 JNDI 数据源,其连接池用于连接到底层数据库。

    以下是我的 Glassfish 域配置文件 ( domain.xml ) 的片段,其中连接池 (GalleriaPool) 由 JNDI 数据源 (jdbc/galleriaDS) 使用,最终由 JDBC 领域 (GalleriaRealm) 使用:
    <domain log-root="${com.sun.aas.instanceRoot}/logs" application-root="${com.sun.aas.instanceRoot}/applications" version="12">
      <resources>
        ...
        <jdbc-connection-pool validation-table-name="SYSIBM.SYSDUMMY1" driver-classname="" datasource-classname="org.apache.derby.jdbc.ClientDataSource40" res-type="javax.sql.DataSource" description="" name="GalleriaPool" is-connection-validation-required="true" fail-all-connections="true" ping="true">
          <property name="User" value="APP"></property>
          <property name="DatabaseName" value="GALLERIA"></property>
          <property name="RetrieveMessageText" value="true"></property>
          <property name="CreateDatabase" value="true"></property>
          <property name="Password" value="APP"></property>
          <property name="ServerName" value="localhost"></property>
          <property name="Ssl" value="off"></property>
          <property name="SecurityMechanism" value="4"></property>
          <property name="TraceFileAppend" value="false"></property>
          <property name="TraceLevel" value="-1"></property>
          <property name="PortNumber" value="1527"></property>
          <property name="LoginTimeout" value="0"></property>
        </jdbc-connection-pool>
        <jdbc-resource pool-name="GalleriaPool" description="" jndi-name="jdbc/galleriaDS"></jdbc-resource>
      </resources>
      <servers>
        <server name="server" config-ref="server-config">
        ...
          <resource-ref ref="jdbc/galleriaDS"></resource-ref>
        </server>
      </servers>
      ...
      <configs>
        <config name="server-config">
        ...
          <security-service>
            <auth-realm name="GalleriaRealm" classname="com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm">
              <property name="jaas-context" value="jdbcRealm"></property>
              <property name="encoding" value="Hex"></property>
              <property name="password-column" value="PASSWORD"></property>
              <property name="datasource-jndi" value="jdbc/galleriaDS"></property>
              <property name="group-table" value="USERS_GROUPS"></property>
              <property name="charset" value="UTF-8"></property>
              <property name="user-table" value="USERS"></property>
              <property name="group-name-column" value="GROUPID"></property>
              <property name="digest-algorithm" value="SHA-512"></property>
              <property name="user-name-column" value="USERID"></property>
            </auth-realm>
            ...
          </security-service>
        </config>
        ...
      </configs>
      ...
    </domain>
    

    更新 #2 - 获取 JDBC 领域针对 Derby 执行的 SQL 语句

    看起来 SQL 查询的结构与您准备的数据库模型不匹配。您可以通过 derby.language.logStatementText 查看 JDBC 领域针对 Derby 实例执行的 SQL 语句。系统属性。此属性可以设置为 true作为 derby.properties 中的静态值文件,并在您重新启动 Derby 实例时生效。 derby.properties文件需要有以下条目:
    derby.language.logStatementText=true
    

    并且这个文件必须放在Derby 实例的当前工作目录中。当前工作目录通常是包含 Derby 数据库的目录,可以使用 derby.system.home 显式指定。 JVM 参数,在 Derby 启动期间:
    -Dderby.system.home=C:\derby
    

    Derby 执行的所有 SQL 语句现在都将记录在 derby.log 中。文件。

    根据提供的信息,我的印象是有一个单独的表,名为 GROUPS用于存储组信息,这与连接表不同 - USER_GROUP .在这种情况下,您的领域必须配置为将组表设为 USER_GROUP。而不是 GROUP ;您可以通过查看 JDBC 领域发出的 SQL 查询来确认这一点。

    为澄清上述观点,JDBC 领域配置中的 Group 字段不用于指定存储组信息的表。相反,它用于指定存储组用户映射的表。在 1:1 映射中,Group 表可以存储此信息,但在 1:M 或通常在 M:M 方案中,您将有一个包含映射的单独表。 JDBC 领域发出的 SQL 查询使用映射表而不是实际的组表(如果它们不同)来确定用户所属的组。

    关于java - Glassfish 3 安全性 - 使用 JDBC 领域的基于表单的身份验证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7944963/

    相关文章:

    jsf - h :commandLink causes JS Uncaught TypeError: Cannot set property 'adp' of null

    java - serverError : class java. lang.ClassCastException java.lang.Integer 无法转换为 java.lang.String

    java - Ant unless 属性不起作用?

    java - 从 Java Integer 到 Scala Int : toInt vs unbox? 的正确方法

    security - 通过 Powershell 在 IIS 7.5 中启用模拟

    azure - Terraform 在 Azure SQL 数据库中启用 Microsoft Defender for SQL

    c# - Thinktecture - 无法在 Web API 中处理加密的 SAML 安全 token

    Java合并相邻的数组元素以产生最大最小值

    c# - 处理泛型时编译器的无用期望?

    java - 单个网页支持多语言