Я хочу понять безопасность на основе форм и области 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...
}
Когда БД была готова, я добавил некоторые данные вручную
Следующим шагом была настройка области безопасности.
Затем добавил конфигурацию безопасности в мой файл 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 по умолчанию на имя пользователя посетителей.Но он все еще не работает
И я также добавил еще несколько опций в свою конфигурацию Realm
Но когдая пытаюсь войти, я все еще вижу исключение, которое говорит:
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
Возможно, что-то не так спул соединений.Вот так выглядит мой пул соединений:
У меня мало свойств,может быть, чего-то не хватает?
Также теперь я создал ресурс 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") Открытый класс 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