Подтвердить что ты не робот

Безопасность Glassfish 3 - аутентификация на основе форм с использованием JDBC Realm

Я хочу понять безопасность на основе форм и области JDBC с помощью glassfishV3, поэтому я решил создать небольшое приложение, которое просто позволяет входить и выходить, я следовал инструкциям из этого 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 [email protected]:"/>
        <h:inputText id="j_username" autocomplete="off" />
        <br/>
        <h:outputLabel id="passwordLabel" for="j_password" value="Enter your [email protected] 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: не удается проверить пользователя [[email protected]] для JDBC область. ПРЕДУПРЕЖДЕНИЕ: Ошибка входа в Интернет: Ошибка входа: javax.security.auth.login.LoginException: исключение безопасности ПРЕДУПРЕЖДЕНИЕ: PWC4011: невозможно установить кодировку символов запроса в UTF-8 из контекст /CHAPTER _12_x_Container_Managed_Authentication_and_Authorization, потому что параметры запроса уже прочитаны или ServletRequest.getReader() уже был вызван

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

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

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

Обновление

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

enter image description here

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

enter image description here

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

SEVERE: SEC1112: не удается проверить пользователя [[email protected]] для JDBC область. ПРЕДУПРЕЖДЕНИЕ: Ошибка входа в Интернет: Ошибка входа: javax.security.auth.login.LoginException: исключение безопасности ПРЕДУПРЕЖДЕНИЕ: PWC4011: невозможно установить кодировку символов запроса в UTF-8 из контекст /CHAPTER _12_x_Container_Managed_Authentication_and_Authorization, потому что параметры запроса уже прочитаны или ServletRequest.getReader() уже был вызван

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

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

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

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

- Может быть, я не могу использовать PASSWORD в качестве имени столбца, потому что он создает какой-то конфликт?

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

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

Обновление 2

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

FINE: Перехват ввода:     перехват: SOAP     defaultServerID: null     defaultClientID: null FINE: ID Entry:     Класс модуля: com.sun.xml.wss.provider.ClientSecurityAuthModule     id: XWS_ClientProvider     тип: клиент     политика запроса: [email protected]     политика ответа: [email protected]     options: {signature.key.alias = s1as, debug = false, dynamic.username.password = false, encryption.key.alias = s1as} FINE: ID Вступление:     Класс модуля: com.sun.xml.wss.provider.ClientSecurityAuthModule     id: ClientProvider     тип: клиент     политика запроса: [email protected]     политика реагирования: [email protected]     options: {signature.key.alias = s1as, debug = false, dynamic.username.password = false, encryption.key.alias = s1as, security.config = C:\jeeAplicationServer\glassfishv3\GlassFish\доменов\домен1/конфигурация/WSS-сервер конфигурация-1.0.xml} FINE: ID Entry:     Класс модуля: com.sun.xml.wss.provider.ServerSecurityAuthModule     id: XWS_ServerProvider     Тип: сервер     политика запроса: [email protected]     политика ответа: [email protected]     options: {signature.key.alias = s1as, debug = false, encryption.key.alias = s1as} FINE: ID Entry:     Класс модуля: com.sun.xml.wss.provider.ServerSecurityAuthModule     id: ServerProvider     Тип: сервер     политика запроса: [email protected]     политика ответа: [email protected]     options: {signature.key.alias = s1as, debug = false, encryption.key.alias = s1as, security.config = C:\jeeAplicationServer\glassfishv3\GlassFish\доменов\домен1/конфигурация/WSS-сервер конфигурация-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: [Web-Security] hasUserDataPermission perm: (javax.security.jacc.WebUserDataPermission/j_security_check POST) FINE: [Web-Security] hasUserDataPermission isGranted: true FINE: Вход в систему [admi[email protected]] в область: DBRealm с использованием JAAS module: jdbcRealm FINE: модуль входа в систему инициализирован: класс com.sun.enterprise.security.auth.login.JDBCLoginModule SEVERE: SEC1112: Невозможно проверить пользователя [[email protected]] для области JDBC. FINE: Не удалось проверить пользователя javax.security.auth.login.LoginException: невозможно для подключения к datasource 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)   в com.sun.enterprise.security.auth.login.PasswordLoginModule.authenticateUser(PasswordLoginModule.java:90)   в com.sun.appserv.security.AppservPasswordLoginModule.login(AppservPasswordLoginModule.java:141)   at sun.reflect.NativeMethodAccessorImpl.invoke0 (Нативный метод) в sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)   в sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)   в java.lang.reflect.Method.invoke(Method.java:597) в 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)   в 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)   на java.lang.Thread.run(Thread.java:662) Вызвано: javax.naming.NamingException: не удалось выполнить поиск для 'jdbc/security' в SerialContext [Исключение корня - 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 more Причиненный: 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 отменена. ПРЕДУПРЕЖДЕНИЕ: Ошибка входа в Интернет: Логин failed: javax.security.auth.login.LoginException: исключение безопасности FINE: идентификатор контекста политики [Web-Security]: 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

Может быть, есть что-то wron с пулом соединений. Вот как выглядит мой пул соединений:

enter image description here

enter image description here

enter image description here

У меня нет свойств, возможно, что-то не хватает?

Также теперь я создал ресурс JDBC, который выглядит следующим образом:

enter image description here

(Имя JNDI в Realm, было изменено на 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"), [email protected](name="groupid", referencedColumnName= "groupid") )
        private Group group;
        //GET & SET METHODS

@Entity @Table (name= "GROUPS", schema = "ADMIN" ) группа public class реализует Serializable {

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

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

//GET и SET METHODS

Поэтому мне также пришлось отредактировать 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 [[email protected]] 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 [[email protected]].
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 : [email protected]
FINE: permission check done to set SecurityContext
FINE: Set security context as user: [email protected]
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 : [email protected]
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 : [email protected], 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
4b9b3361

Ответ 1

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

  • Пароль хранится в открытом виде в базе данных. Это, скорее всего, неверно. 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. В документации это явно указано:

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

Обновление

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

Ниже приведен фрагмент моего файла конфигурации домена Glassfish (domain.xml), где пул соединений (GalleriaPool) используется JNDI DataSource (jdbc/galleriaDS), который в конечном итоге используется в 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 - Получение инструкций SQL, выполняемых в JDBC Realm против 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 не используется для указания таблицы, в которой хранится информация о группе. Вместо этого он используется для указания таблицы, в которой хранятся сопоставления Group-User. При сопоставлении 1:1 таблица Group может хранить эту информацию, но в 1: M или, как правило, в сценарии M: M, у вас будет отдельная таблица, содержащая сопоставление. SQL-запрос, выданный областью JDBC, использует таблицу сопоставления, а не фактическую таблицу групп (если они разные), чтобы определить группы, к которым принадлежит пользователь.

Ответ 2

Помимо ответа от Vineet, я также заметил, что опция Security Manager не отмечена на вкладке "Безопасность" GlassFish, этот параметр должен быть включен, чтобы использовать Security в вашем королевстве.

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

Ответ 3

Я уже делал это на 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.

Ответ 4

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

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

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

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

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