Безопасность Glassfish 3 - аутентификация на основе форм с использованием JDBC Realm - PullRequest
24 голосов
/ 30 октября 2011

Я хочу понять безопасность на основе форм и области JDBC с glassfishV3, поэтому я решил создать небольшое приложение, которое позволяет просто входить и выходить из системы. Я следовал инструкциям из этой книги , чтобы сделать это.

Я понимаю, как работает удержание, но что-то не так, и я не могу заставить его работать должным образом.

Сначала я создал небольшую базу данных с аннотациями 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: Невозможно проверить пользователя [admin@gmail.com] для области JDBC.ВНИМАНИЕ: Web Войти не удалось: Логин не удалось: javax.security.auth.login.LoginException: Безопасность Exception ПРЕДУПРЕЖДЕНИЕ: PWC4011: Невозможно установить кодировку запроса символов в UTF-8 из контекста / CHAPTER_12_x_Container_Managed_Authentication_and_Authorization, поскольку параметры запроса уже считаны или ServletRequest.getReader () уже был вызван

2 - Когда я пытаюсь перейти на некоторые страницы через URL, ничего не происходит.Я думаю, что это нормально, но когда я пытаюсь посетить visitorpanel.xhtml, он должен позволить мне, потому что нет необходимости входить в систему, чтобы увидеть это.Нужно ли мне удалять эту страницу из конфигурации безопасности, если хотите, чтобы каждый ее видел?

3 - Мне также любопытно, почему я не могу использовать тег h: form вместо простой формы, когда я реализую имя входа?

Я действительно ценю некоторую помощь, я несколько часов читалпервые главы книги и попытка реализовать свой собственный пример, но я застрял.Я думаю, что я близок к решению.

Обновление

Я изменил принципал Default по умолчанию на имя пользователя посетителей.Но он все еще не работает

enter image description here

И я также добавил еще несколько опций в свою конфигурацию Realm

enter image description here

Но когдая пытаюсь войти, я все еще вижу исключение, которое говорит:

SEVERE: SEC1112: Невозможно проверить пользователя [admin@gmail.com] для области JDBC.ВНИМАНИЕ: Web Войти не удалось: Логин не удалось: javax.security.auth.login.LoginException: Безопасность Exception ПРЕДУПРЕЖДЕНИЕ: PWC4011: Невозможно установить кодировку запроса символов в UTF-8 из контекста / CHAPTER_12_x_Container_Managed_Authentication_and_Authorization, поскольку параметры запроса уже считаны или ServletRequest.getReader () уже был вызван

Я до сих пор не знаю, чего не хватает.

- Может быть, имя таблицы не должно быть в верхнем регистре?

-Может ли быть так, что имена столбцов не должны быть в верхнем регистре?

-Может быть, что таблицы созданы неправильно?

-Может быть, я не могу использовать ПАРОЛЬ какимя столбца, потому что это создает какой-то конфликт?

Я действительно не понимаю, почему это исключение.Я пинговал базу данных из админ-панели, и все кажется правильным.

Может кто-нибудь помочь мне разобраться с этим?

Обновление 2

Я изменил параметр ведения журнала 'javax.enterprise.system.core.security' на уровень FINE, чтобы получить больше информации при возникновении исключений, это был результат, когда я пытался войти в систему:

FINE: запись перехвата: intercept: SOAP defaultServerID: null defaultClientID: null FINE: ID запись: класс модуля: com.sun.xml.wss.provider.ClientSecurityAuthModule id: XWS_ClientProvider тип: политика запроса клиента: 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} FINE:Идентификационная запись: класс модуля: com.sun.xml.wss.provider.ClientSecurityAuthModule id: тип клиента: тип запроса клиента: 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, безопасность.config = C: \ jeeAplicationServer \ glassfishv3 \ glassfish \ domains \ domain1 / config / wss-server-config-1.0.xml} FINE: ID Запись: класс модуля: com.sun.xml.wss.provider.ServerSecurityAuthModule, идентификатор: XWS_ServerProviderтип: политика запроса к серверу: 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: тип сервера-провайдера: политика запроса сервера: 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] Настройка идентификатора контекста политики: old = null ctxID = CHAPTER_x_12_Container_Managed_Authentication_and_Authorization / CHAPTER_x_12_Container_Managed_Authentication_and_Authorization FINE: [веб-безопасность] hasUserDataPermission perm: (javax.security.jacc.WebUserDataPermission / j_security_check POST) FINE: [веб-безопасность] hasUserDataPermission isGranted: истинная пользовательская администрация: true FINE:используя модуль JAAS: jdbcRealm. FINE: инициализирован модуль входа в систему: класс com.sun.enterprise.security.auth.login.JDBCLoginModule. SEVERE: SEC1112: невозможно проверить пользователя [admin@gmail.com] для области JDBC.FINE: невозможно проверить пользователя. Javax.security.auth.login.LoginException: невозможно подключиться к источнику данных jdbc / security для пользователя базы данных.в com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm.getConnection (JDBCRealm.java:550) в com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm.isUserValid (JDBCRealm.java:393)в com.sun.enterprise.security.auth.realm.jdbc.JDBCRealm.authenticate (JDBCRealm.java:311) в com.sun.enterprise.security.auth.login.JDBCLoginModule.authenticate (JDBCLoginModule.java:72 в).sun.enterprise.security.auth.login.Метод) в sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:39) в sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:25) в java.lanketo.j.jjjavax.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)в java.security.AccessController.doPrivileged (собственный метод) в javax.security.auth.login.LoginContext.invokePriv (LoginContext.java:680) в javax.security.auth.login.LoginContext.login (LoginContext.java:579) в com.sun.enterprise.security.auth.login.LoginContextDriver.doPasswordLogin (LoginContextDriver.java:341) в com.sun.enterprise.security.auth.login.LoginContextDriver.login (LoginContextDriver.java:199) в com.sun.enterprise.security.auth.login.LoginContextDriver.login (LoginContextDriver.java:152) в com.sun.web.security.RealmAdapter.authenticate (RealmAdapter.java:479) в com.sun.web.security.RealmAdapter.authenticate (RealmAdapter.java:418) в org.apache.catalina.authenticator.FormAuthenticator.authenticate (FormAuthenticator.java:264) в org.apache.catalina.authenticator.AuthenticatorBase.processSecurityCheck (AuthenticatorBase.java:1015) в org.apache.catalina.authenticator.AuthenticatorBase.invoke (AuthenticatorBase.java:614) в org.apache.catalina.core.StandardPipeline.invoke (StandardPipeline.java:615) на com.sun.enterprise.web.WebPipeline.invoke (WebPipeline.java:97) на com.sun.enterprise.web.PESessionLockingStandardPipeline.invoke (PESessionLockingStandardPipeline.java:85) в org.apache.catalina.core.StandardHostValve.invoke (StandardHostValve.java:185) в org.apache.catalina.connector.CoyoteAdapter.doService (CoyoteAdapter.java:325) в org.apache.catalina.connector.CoyoteAdapter.service (CoyoteAdapter.java:226) в com.sun.enterprise.v3.services.impl.ContainerMapper.service (ContainerMapper.java:165) в com.sun.grizzly.http.ProcessorTask.invokeAdapter (ProcessorTask.java:791) в com.sun.grizzly.http.ProcessorTask.doProcess (ProcessorTask.java:693) на com.sun.grizzly.http.ProcessorTask.process (ProcessorTask.java:954) в com.sun.grizzly.http.DefaultProtocolFilter.execute (DefaultProtocolFilter.java:170) в com.sun.grizzly.DefaultProtocolChain.executeProtocolFilter (DefaultProtocolChain.java:135) в com.sun.grizzly.DefaultProtocolChain.execute (DefaultProtocolChain.java:102) в com.sun.grizzly.DefaultProtocolChain.execute (DefaultProtocolChain.java:88) в com.sun.grizzly.http.HttpProtocolChain.execute (HttpProtocolChain.java:76) в com.sun.grizzly.ProtocolChainContextTask.doCall (ProtocolChainContextTask.java:53) в com.sun.grizzly.SelectionKeyContextTask.call (SelectionKeyContextTask.java:57) в com.sun.grizzly.ContextTask.run (ContextTask.java:69) в com.sun.grizzly.util.AbstractThreadPool $ Worker.doWork (AbstractThreadPool.java:330) в com.sun.grizzly.util.AbstractThreadPool $ Worker.run (AbstractThreadPool.java:309) at java.lang.Thread.run (Thread.java:662) Вызывается: javax.naming.NamingException: не удалось выполнить поиск для «jdbc / security» в SerialContext [Исключением Root является javax.naming.NameNotFoundException: безопасность не найдена] в com.sun.enterprise.naming.impl.SerialContext.lookup (SerialContext.java:442) в javax.naming.InitialContext.lookup (InitialContext.java:392) в javax.naming.InitialContext.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) в com.sun.enterprise.naming.impl.TransientContext.lookup (TransientContext.java:168) в com.sun.enterprise.naming.impl.TransientContext.lookup (TransientContext.java:172) в com.sun.enterprise.naming.impl.SerialContextProviderImpl.lookup (SerialContextProviderImpl.java:58) вcom.sun.enterprise.naming.impl.LocalSerialContextProviderImpl.lookup (LocalSerialContextProviderImpl.java:101) в com.sun.enterprise.naming.impl.SerialContext.lookup (SerialContext.java:430) ... еще 49 *

FINE: аутентификация JAAS прервана.ВНИМАНИЕ: Сбой входа в систему через Интернет: Ошибка входа: javax.security.auth.login.LoginException: Исключение безопасности FINE: ИД контекста политики [Web-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

(Имя 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") Открытый класс Group реализует Serializable {

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

Ответы [ 4 ]

18 голосов
/ 30 октября 2011

В вашей конфигурации несколько пропущенных битов:

  • Пароль хранится в открытом виде в базе данных. Это, скорее всего, неверно. 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 не позволяет указывать атрибут action тега h:form. Это значение устанавливается средой выполнения JSF при кодировании ответа, и поэтому вы не сможете указать значение j_security_check при использовании тега h:form. Документация прямо заявляет об этом :

Значение атрибута "action" должно быть результатом передачи просмотреть идентификатор текущего представления для метода getActionURL() ViewHandler для этого приложения, затем передать эту строку в encodeActionURL() метод на ExternalContext.

Обновление

Основываясь на опубликованной трассировке стека, я могу заключить, что источник данных JNDI (указанный в поле JNDI), который будет использоваться Царством, недоступен в домене Glassfish. Одним из предварительных условий для JDBC Realm является регистрация источника данных JNDI в конфигурации домена Glassfish, пул соединений которого используется для подключения к базовой базе данных.

Ниже приведен фрагмент моего файла конфигурации домена 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 - Получение операторов SQL, выполняемых областью JDBC для Derby

Похоже, что структура запроса SQL не соответствует модели базы данных, которую вы подготовили. Вы можете взглянуть на операторы SQL, выполняемые областью JDBC для экземпляра Derby, через системное свойство derby.language.logStatementText. Это свойство может быть установлено в true как статическое значение в файле derby.properties, и оно вступит в силу при перезапуске экземпляра Derby. Файл derby.properties должен содержать следующую запись:

derby.language.logStatementText=true

и этот файл должен быть помещен в текущий рабочий каталог экземпляра Derby. Текущий рабочий каталог часто является каталогом, содержащим базы данных Derby, и его можно явно указать с помощью аргумента derby.system.home JVM при запуске Derby:

-Dderby.system.home=C:\derby

Все операторы SQL, выполняемые Derby, теперь будут регистрироваться в файле derby.log.

На основании предоставленной информации у меня сложилось впечатление, что существует отдельная таблица с именем GROUPS, котораяиспользуется для хранения информации о группе, и это отличается от таблицы соединения - USER_GROUP.В этом сценарии ваша область должна быть настроена так, чтобы иметь таблицу группы как USER_GROUP, а не GROUP;Вы можете убедиться в этом, посмотрев запросы SQL, выданные областью JDBC.

Чтобы пояснить вышеизложенное, поле Group в конфигурации области JDBC не используется для указания таблицы, в которой хранится информация о группе.Вместо этого он используется для указания таблицы, в которой хранятся сопоставления групп пользователей.В отображении 1: 1 таблица Group может хранить эту информацию, но в случае 1: M или, как правило, в сценарии M: M, у вас будет отдельная таблица, содержащая сопоставление.Запрос SQL, выданный областью JDBC, использует таблицу сопоставления, а не фактическую таблицу групп (если они различаются), чтобы определить группы, к которым принадлежит пользователь.

3 голосов
/ 31 октября 2011

Вдобавок к ответу от Vineet, я также заметил, что на вкладке «Безопасность» GlassFish не включена опция «Менеджер безопасности», эта опция должна быть включена, чтобы использовать «Безопасность» в вашей сфере.

Еще одна вещь, если вы используете имя JDBC JDBC, вам не нужно указывать имя пользователя / пароль для области JDBC

2 голосов
/ 15 ноября 2011

Я столкнулся с той же проблемой.

Я решил эту проблему, переименовав пароль в (User_password) и поля userName (User_name) в таблице (что-нибудь кроме имени пользователя и пароля), каким-то образомиспользование «userName» и «пароля» вызывает некоторые конфликты при выполнении аутентификации с использованием Realms.

Также добавьте алгоритм дайджеста: = нет, если вы храните пароль в виде простого текста.

В безопасностименю, Включить принципала по умолчанию для сопоставления ролей.

Надеюсь, это поможет,

2 голосов
/ 08 ноября 2011

Я уже делал это на Sailfin (на основе Glassfish 2).

Во-первых, я не вижу ни одного файла sun-web.xml, который сопоставляет роли, определенные в вашем файле web.xml, с группами, определенными в базе данных.

Во-вторых, согласно этому руководству: http://codepimpsdotorg.blogspot.com/2007/12/glassfish-jdbc-realm-authentication.html вы должны указать алгоритм дайджеста («none» не вариант, не уверен, что он останется таким же в 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.

...