簡體   English   中英

Glassfish 3安全性 - 使用JDBC Realm進行基於表單的身份驗證

[英]Glassfish 3 security - Form based authentication using a JDBC Realm

我想通過glassfishV3了解基於表單的安全性和JDBC領域,所以我決定創建一個允許登錄和退出的小應用程序,我按照本書中的說明進行操作。

我理解保持的東西是如何工作的,但是有些東西是錯的,我不能讓它正常工作。

我首先做的是用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...
    }

當數據庫准備就緒時,我手動添加了一些數據

在此輸入圖像描述

下一步是配置安全領域。

在此輸入圖像描述

然后將安全配置添加到我的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頁面,在控制台中我看到一個異常:

嚴重:SEC1112:無法驗證JDBC領域的用戶[admin@gmail.com]。 警告:Web登錄失敗:登錄失敗:javax.security.auth.login.LoginException:安全異常警告:PWC4011:無法從上下文/ CHAPTER_12_x_Container_Managed_Authentication_and_Authorization將請求字符編碼設置為UTF-8,因為已經讀取了請求參數或ServletRequest .getReader()已被調用

2-當我嘗試通過URL導航到某些頁面時,沒有任何反應。 我認為沒關系,但是當我嘗試訪問visitorpanel.xhtml時,它應該讓我,因為沒有必要登錄才能看到它。 如果想讓每個人都看到它,我是否需要從安全配置中刪除該頁面?

3-此外,我很好奇為什么我不能使用標簽h:form而不僅僅是表單,當我實現登錄時?

我非常感謝一些幫助,我已經花了幾個小時閱讀本書的第一章並嘗試實施,我自己的例子但我卡住了。 我想我接近解決方案。

更新

我將Default主體更改為訪問者用戶名。 但它仍然無效

在此輸入圖像描述

我還為我的Realm配置添加了一些選項

在此輸入圖像描述

但是當我嘗試登錄時,我仍然看到一個例外情況:

嚴重:SEC1112:無法驗證JDBC領域的用戶[admin@gmail.com]。 警告:Web登錄失敗:登錄失敗:javax.security.auth.login.LoginException:安全異常警告:PWC4011:無法從上下文/ CHAPTER_12_x_Container_Managed_Authentication_and_Authorization將請求字符編碼設置為UTF-8,因為已經讀取了請求參數或ServletRequest .getReader()已被調用

我還是不知道遺失了什么。

- 表名不應該是大寫嗎?

- 列名不應該是大寫的嗎?

- 表格創建錯誤嗎?

- 我不能使用PASSWORD作為列名,因為它會產生某種沖突嗎?

我真的不明白為什么那個例外。 我從管理面板中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響應策略:javax.security.auth.message.MessagePolicy@310a6d選項:{signature.key.alias = s1as,debug = false,dynamic.username.password = false,encryption.key.alias = s1as}精細: ID條目:模塊類:com.sun.xml.wss.provider.ClientSecurityAuthModule id:ClientProvider類型:客戶端請求策略:javax.security.auth.message.MessagePolicy@1829770響應策略:javax.security.auth.message.MessagePolicy @ a4461e選項:{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條目:模塊類:com.sun.xml.wss.provider.ServerSecurityAuthModule id:XWS_ServerPro vider類型:服務器請求策略:javax.security.auth.message.MessagePolicy@f79c86響應策略:javax.security.auth.message.MessagePolicy@454bf7選項:{signature.key.alias = s1as,debug = false,encryption.key .alias = s1as} FINE:ID條目:模塊類:com.sun.xml.wss.provider.ServerSecurityAuthModule id:ServerProvider類型:服務器請求策略:javax.security.auth.message.MessagePolicy@17e85e4響應策略:javax.security .auth.message.MessagePolicy @ 1887906選項:{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]設置策略上下文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] hasUserDat aPermission isGranted:true FINE:使用JAAS模塊登錄用戶[admin@gmail.com]:DBRealm:jdbcRealm FINE:初始化登錄模塊:class com.sun.enterprise.security.auth.login.JDBCLoginModule SEVERE:SEC1112:不能驗證JDBC領域的用戶[admin@gmail.com]。 FINE:無法驗證用戶javax.security.auth.login.LoginException:無法連接到數據庫用戶用戶的數據源jdbc / security。 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方法)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)位於javax.security.auth.login.LoginContext.access $ 000(LoginContext.java: 186)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)在com.sun的com.sun.enterprise.security.auth.login.LoginContextDriver.doPasswordLogin(LoginContextDriver.java:341)的javax.security.auth.login.LoginContext.login(LoginContext.java:579)。 enterprise.security.auth.login.LoginContextDriver.login(LoginContextDriver.java:199)位於com.sun.web.security的com.sun.enterprise.security.auth.login.LoginContextDriver.login(LoginContextDriver.java:152)。 RealmAdapter.authenticate(RealmAdapter.java:479)位於org.apache.catalina.authenticator.FormAuthenticator.authenticate(FormAuthenticator.java:264)的com.sun.web.security.RealmAdapter.authenticate(RealmAdapter.java:418) .apache.catalina.authenticator.AuthenticatorBase.processSecurityCheck(AuthenticatorBase.java:1015)at org.apache.catalina.authenticator.AuthenticatorBase.invoke(Authenti) catorBase.java:614)位於com.sun.enterprise的com.sun.enterprise.web.WebPipeline.invoke(WebPipeline.java:97)的org.apache.catalina.core.StandardPipeline.invoke(StandardPipeline.java:615)位於org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:185)的org.apache.catalina.connector.CoyoteAdapter.doService上的.web.PESessionLockingStandardPipeline.invoke(PESessionLockingStandardPipeline.java:85)(CoyoteAdapter.java:325 )在com.sun.grizzly的com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:165)的org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:226)。 http.ProcessorTask.invokeAdapter(ProcessorTask.java:791)位於com.sun.grizzly.http.ProcessorTask.doProcess(ProcessorTask.java:693)的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)引起:javax.naming.NamingException:在com.sun.enterprise中查找SerialContext中的'jdbc / security'失敗[根異常是javax.naming.NameNotFoundException:找不到安全性]位於javax.naming.InitialCo的javax.naming.InitialContext.lookup(InitialContext.java:392)的.naming.impl.SerialContext.lookup(SerialContext.java:442) n.sk.lookup(InitialContext.java:392)位於com.sun.enterprise.connectors.service.ConnectorResourceAdminServiceImpl.lookup(ConnectorResourceAdminServiceImpl.java:203)的com.sun.enterprise.connectors.ConnectorRuntime.lookupNonTxResource(ConnectorRuntime.java:440)在com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm.getConnection(JDBCRealm.java:538)... 44更多引起:javax.naming.NameNotFoundException: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)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更多

精細:JAAS身份驗證中止。 警告:Web登錄失敗:登錄失敗:javax.security.auth.login.LoginException:安全異常FINE:[Web-Security]策略上下文ID為: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

也許連接池有一些問題。 這是我的連接池的樣子:

在此輸入圖像描述

在此輸入圖像描述

在此輸入圖像描述

我沒有太多屬性,也許有些東西丟失了?

此外,我現在創建了一個JDBC資源,如下所示:

在此輸入圖像描述

(領域中的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>

我想我取得了一些進展,現在我看到的例外是:

> 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

@Entity @Table(name =“GROUPS”,schema =“ADMIN”)public class Group實現Serializable {

private static final long serialVersionUID = -7274308564659753174L;
@Id
@Column(nullable = false)
private String groupid;

@OneToMany(mappedBy="group")
private Set<User> users;

//獲取和設置方法

所以我還要編輯DBRealm,現在它看起來像這樣:

在此輸入圖像描述

但是當我登錄時,我又得到一個例外:

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 Realm將無法對用戶進行身份驗證,因為數據庫中的存儲值與Realm創建的摘要不匹配。 您需要在領域配置中指定顯式摘要算法,或者依賴於默認值。 此外,您需要確保應用程序在創建新用戶或修改其密碼時創建摘要。 如果要以明文形式存儲密碼,則必須為摘要算法指定值“none”。
  • 僅指定摘要算法是不夠的。 您需要指定存儲摘要的編碼(因為,摘要只是一個字節序列,並且可能不會存儲為純ASCII序列)。 Glassfish支持Hex和Base64編碼,默認使用Hex編碼。 因此 ,在存儲密碼摘要之前, 您的應用應該應用與域中配置的編碼相同的編碼 請注意,當您指定摘要算法“none”以明文形式存儲密碼時,您無需對存儲的密碼進行編碼(同樣,您也無需指定編碼); 至少這是我從閱讀Glassfish資料中觀察到的。
  • 此外,用戶組映射目前似乎是1:1。 您可能希望使用單獨的連接表來允許組和用戶之間的1:N映射。
  • 您還需要確保啟用“默認主體到角色映射”選項。 如果沒有此選項,則需要手動將web.xml中的角色映射到領域中的用戶和組

關於使用form而不是h:form的主題,其根本原因是JSF運行時不允許您指定h:form標記的action屬性。 在對響應進行編碼時,此值由JSF運行時設置,因此,當您使用h:form標記時,將無法指定j_security_check的值。 文檔明確說明了這一點

“action”屬性的值必須是將當前視圖的視圖標識符傳遞給此應用程序的ViewHandlergetActionURL()方法,然后將該String傳遞給ExternalContext上的encodeActionURL()方法的結果。

更新

基於發布的堆棧跟蹤,我可以推斷出Realm使用的JNDI數據源(在JNDI字段中指定)在Glassfish域中不可用。 JDBC Realm的先決條件之一是在Glassfish域配置中注冊JNDI數據源,其連接池用於連接到底層數據庫。

以下是我的Glassfish域配置文件( domain.xml )的片段,其中JNDI DataSource(jdbc / galleriaDS)使用連接池(GalleriaPool),最終由JDBC Realm(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 Realm針對Derby執行的SQL語句

看起來SQL查詢的結構與您准備的數據庫模型不匹配。 您可以通過derby.language.logStatementText系統屬性derby.language.logStatementText JDBC領域針對Derby實例執行的SQL語句。 可以將此屬性設置為true作為derby.properties文件中的靜態值,它將在重新啟動Derby實例時生效。 derby.properties文件需要具有以下條目:

derby.language.logStatementText=true

並且此文件必須放在Derby實例的當前工作目錄中。 當前工作目錄通常是包含Derby數據庫的目錄,並且可以在Derby啟動期間使用derby.system.home JVM參數顯式指定:

-Dderby.system.home=C:\derby

Derby執行的所有SQL語句現在都將記錄在derby.log文件中。

根據提供的信息,我的印象是有一個名為GROUPS的單獨表用於存儲組信息,這與連接表 - USER_GROUP 在這種情況下,您的域必須配置為將Group表作為USER_GROUP而不是GROUP ; 您可以通過查看JDBC領域發出的SQL查詢來確認這一點。

為了澄清上述觀點,JDBC領域配置中的Group字段不用於指定存儲組信息的表。 相反,它用於指定存儲組 - 用戶映射的表。 在1:1映射中,Group表可以存儲此信息,但在1:M或通常在M:M場景中,您將擁有一個包含映射的單獨表。 JDBC領域發出的SQL查詢使用映射表而不是實際的組表(如果它們不同)來確定用戶所屬的組。

除了Vineet的答案之外,我還注意到在GlassFish的Security選項卡中沒有選中選項安全管理器,應該啟用該選項以便在您的Realm中使用Security。

如果您使用JDBC JNDI名稱,則不需要為JDBC領域提供用戶名/密碼

我已經在Sailfin上做了這個(基於Glassfish 2)。

首先,我沒有看到任何sun-web.xml文件將web.xml文件中定義的角色映射到定義數據庫的組。

其次,根據本教程: http//codepimpsdotorg.blogspot.com/2007/12/glassfish-jdbc-realm-authentication.html您必須指定一個摘要算法(“無”不是一個選項,不確定它是否仍然存在在Glassfish中也是如此3)。

第三,表和列需要按特定順序排列,我們使用以下結構:

@Entity
@Table(name = "AuthenticationUser")
public class UserEntity implements Serializable, Identifiable
{   
    private static final long serialVersionUID = -1213555368237839900L;

    @Id
    @Column(name = "name", length = 20)
    private String itsName;

    @Column(name = "password", length = 1024)
    private String itsPassword;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "groupName", referencedColumnName = "name")
    private GroupEntity itsGroupEntity;
...

@Entity
@Table(name = "AuthenticationGroup")
public class GroupEntity implements Serializable, Identifiable
{
    private static final long serialVersionUID = -1213554368237839900L;

    private static final String USER_GROUP_COLUMN = "itsGroupEntity";

    @Id
    @Column(name = "name", length = 20)
    private String itsName;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY,
            mappedBy=USER_GROUP_COLUMN)
    private List<UserEntity> itsUsers;
...

並定義領域:

user-table=AuthenticationUser
user-name-column=name
password-column=password
group-table=AuthenticationUser
group-name-column=groupName

重要信息:用戶名和組名屬於同一個表! 因此表AuthenticationGroup僅供我們內部使用,但Glassfish不使用。

我遇到了同樣的問題。

我通過將密碼重命名為(User_password)和表中的userName(User_name)字段(除了用戶名和密碼之外的其他任何內容)來解決此問題,以某種方式使用“userName”和“password”在使用Realms執行身份驗證時導致一些沖突。

還要使用摘要算法:= none,以防您將密碼存儲為純文本。

在“安全性”菜單中,啟用“默認主體到角色映射”。

希望這可以幫助,

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM