Glassfish 3 sécurité - authentification basée sur des formulaires à l'aide d'un Realm JDBC
je veux comprendre la sécurité basée sur la forme et les royaumes JDBC avec glassfishV3, donc j'ai décidé de créer une petite application qui permet juste de s'inscrire et sortir, j'ai suivi les instructions de ce Livre pour le faire.
je comprends le fonctionnement du hold-thing, mais quelque chose ne va pas et je ne peux pas le faire fonctionner correctement.
ce que j'ai fait en premier était de créer une petite base de données avec des annotations 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...
}
Voici l'autre table qui contient les rôles pour chaque utilisateur
@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...
}
quand le DB était prêt j'ai ajouté quelques données manuellement
l'étape suivante consistait à configurer un domaine de sécurité.
a ensuite ajouté la configuration de sécurité à mon site web.fichier 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>
mes objectifs ici étaient:
-
les administrateurs peuvent voir toutes les pages
-
les visiteurs ne peuvent voir que l'index.xhtml et visitorpanel.xhtml
-
les utilisateurs peuvent voir l'index.xhtml, visitorpanel.xhtml et userpanel.XHTML
je pense que la configuration est correcte.
Enfin, la dernière étape a été de créer le formulaire de connexion dans l'index.page 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>
le programme se construit bien, mais j'ai les problèmes suivants:
1-Lorsque j'essaie de me connecter en tant qu'utilisateur ou administrateur(les visiteurs n'ont pas besoin de se connecter), je suis redirigé vers l'erreur.page xhtml et dans la console, je vois un exception:
sévère: SEC1112: impossible de valider l'utilisateur [admin@gmail.com] pour JDBC Royaume. Avertissement: l'ouverture de session Web a échoué: L'ouverture de session a échoué: javax.sécurité.auth.connexion.LoginException: avertissement D'Exception de sécurité: PWC4011: impossible de définir L'encodage des caractères de la requête à UTF-8 à partir de cadre / Chapter_12_x_container_managed_authentication_et_authorization, parce que les paramètres de la requête ont déjà été lus, ou ServletRequest.getReader () a déjà été appelé
2-Quand j'essaie de naviguer vers certaines pages via L'URL, rien ne se passe. Je pense que c'est ok, mais quand j'essaie de visiter le paneldes visiteurs.xhtml, il devrait me laisser, car il n'est pas nécessaire d'être connecté pour voir. Dois-je supprimer cette page de la configuration de sécurité si je veux que chaque personne la voit?
3-Aussi je suis curieux de savoir pourquoi je ne peux pas utiliser le tag h: form au lieu de juste form, quand je mets en œuvre le login?
Mauvais apprécie vraiment de l'aide, j'ai quelques heures à lire les premiers chapitres du livre et d'essayer de mettre en œuvre, dans mon exemple, mais je suis coincé. Je pense que je suis proche de la solution.
mise à Jour
j'ai changé le principal par défaut pour être le nom d'Utilisateur des visiteurs. Mais il ne fonctionne toujours pas
et j'ai aussi ajouté quelques options à mon Royaume de configuration
mais quand j'essaie de me connecter je vois encore une exception qui dit:
sévère: SEC1112: impossible de valider l'utilisateur [admin@gmail.com] pour JDBC Royaume. Avertissement: l'ouverture de session Web a échoué: L'ouverture de session a échoué: javax.sécurité.auth.connexion.LoginException: avertissement D'Exception de sécurité: PWC4011: impossible de définir L'encodage des caractères de la requête à UTF-8 à partir de cadre / Chapter_12_x_container_managed_authentication_et_authorization, parce que les paramètres de la requête ont déjà été lus, ou ServletRequest.getReader () a déjà été appelé
je ne sais toujours pas ce qui manque.
- est-ce que le nom de la table ne devrait pas être majuscule?
- est-ce que les noms de colonnes ne devraient pas être en majuscules?
-se Pourrait-il que les tableaux sont créé le mal?
- est-il possible que je ne puisse pas utiliser le mot de passe comme nom de colonne, parce qu'il fait une sorte de conflit?
je ne comprends vraiment pas pourquoi cette exception. J'ai trouvé la base de données dans le panneau d'administration, et tout semble correct.
est-ce que quelqu'un peut m'aider à comprendre celui-ci?
Update 2
j'ai changé le "javax.entreprise.système.core.l'option de journalisation de la sécurité au niveau amende, pour avoir plus d'informations lorsque des exceptions se produisent, ce fut le résultat lorsque j'ai essayé de me connecter:
amende: Intercept Entry: interception: le SAVON defaultServerID: null defaultClientID: null FINE: ID Entry: module de classe: com.soleil.XML.wss.fournisseur de.ClientSecurityAuthModule id: XWS_ClientProvider Type: client stratégie de demande de: javax.sécurité.auth.message.MessagePolicy@e95a72 Politique de réponse: javax.sécurité.auth.message.MessagePolicy@310a6d options: {signature.clé.alias=s1as, debug=false, dynamique.nom d'utilisateur.mot de passe=false, le chiffrement.clé.alias = s1as} FINE: ID Entrée: module de classe: com.soleil.XML.wss.Fournisseur.ClientSecurityAuthModule id: ClientProvider Type: client Politique de demande: javax.sécurité.auth.message.MessagePolicy@1829770 la politique d'intervention: javax.sécurité.auth.message.MessagePolicy@a4461e options: {signature.clé.alias=s1as, debug=false, dynamique.utilisateur.mot de passe=false, le chiffrement.clé.alias = s1as, de sécurité.config=C:jeeAplicationServerglassfishv3glassfishdomaindomain1/config / wss-server-config-1.0.xml} AMENDE: Entrée de l'ID: module de classe: com.soleil.XML.wss.Fournisseur.ServerSecurityAuthModule id: XWS_ServerProvider type: serveur Politique de demande: javax.sécurité.auth.message.MessagePolicy@f79c86 Politique de réponse: javax.sécurité.auth.message.MessagePolicy@454bf7 options: {signature.clé.alias = s1as, debug = false, cryptage.clé.alias = s1as} FINE: ID Entry: module de classe: com.soleil.xml.wss.fournisseur de.ServerSecurityAuthModule id: ServerProvider type: serveur Politique de demande: javax.sécurité.auth.message.MessagePolicy@17e85e4 Politique de réponse: javax.sécurité.auth.message.MessagePolicy@1887906 options: {signature.clé.alias= s1as, debug=false, cryptage.clé.alias = s1as, sécurité.config=C:jeeAplicationServerglassfishv3glassfishdomaindomain1/config / wss-server-config-1.0.XML} Fin: [Web-sécurité] définition du contexte de la Politique ID: old = null ctxID = CHAPTER_x_12_Container_Managed_Authentication_and_authorization/CHAPTER_x_12_Container_Managed_Authentication_and_authorization Amende: [Web-sécurité] hasUserDataPermission perm: (javax.sécurité.jacc.WebUserDataPermission / j_security_check POST) Amende: [Web-sécurité] hasUserDataPermission isGranted: vrai AMENDE: Ouverture de session dans l'utilisateur [admin@gmail.com] into realm: DBREALM using JAAS module: JDBCREALM FINE: module Login initialisé: classe COM.soleil.entreprise.sécurité.auth.connexion.JDBCLOGINMODULE sévère: SEC1112: impossible de valider l'utilisateur [admin@gmail.com] for JDBC realm. FIN: Impossible de valider l'utilisateur javax.sécurité.auth.connexion.LoginException: Impossible pour se connecter à datasource jdbc / sécurité pour l'utilisateur de base de données. à COM.soleil.entreprise.sécurité.auth.Royaume.jdbc.JDBCRealm.getConnection (JDBCRealm.java: 550) à COM.soleil.entreprise.sécurité.auth.Royaume.jdbc.JDBCRealm.isUserValid (JDBCRealm.java: 393) à COM.soleil.entreprise.sécurité.auth.Royaume.jdbc.JDBCRealm.authentifier (JDBCRealm.java: 311) à COM.soleil.entreprise.sécurité.auth.connexion.JDBCLoginModule.authentifier (JDBCLoginModule.java: 72) à COM.soleil.entreprise.sécurité.auth.connexion.PasswordLoginModule.authenticateUser (PasswordLoginModule.java: 90) à COM.soleil.appserv.sécurité.AppservPasswordLoginModule.login (AppservPasswordLoginModule.java: 141) au coucher du soleil.refléter.NativeMethodAccessorImpl.invoke0 (méthode Native) à soleil.de réfléchir.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java: 39) à soleil.refléter.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java: 25) à java.lang.refléter.Méthode.invoke(la Méthode.java:597) à javax.sécurité.auth.connexion.LoginContext.invoke (LoginContext.java: 769) à javax.sécurité.auth.connexion.LoginContext.accès $ 000 (LoginContext.java: 186) à javax.sécurité.auth.connexion.LoginContext 4$.run (LoginContext.java: 683) à java.sécurité.AccessController.d oprivileged (méthode Native) à javax.sécurité.auth.connexion.LoginContext.invokePriv (LoginContext.java: 680) à javax.sécurité.auth.connexion.LoginContext.login (LoginContext.java: 579) à COM.soleil.entreprise.sécurité.auth.connexion.LoginContextDriver.doPasswordLogin (LoginContextDriver.java: 341) à COM.soleil.entreprise.sécurité.auth.connexion.LoginContextDriver.login (LoginContextDriver.java: 199) à COM.soleil.entreprise.sécurité.auth.connexion.LoginContextDriver.login (LoginContextDriver.java: 152) à COM.soleil.Web.sécurité.RealmAdapter.authentifier(RealmAdapter.java: 479) à COM.soleil.Web.sécurité.RealmAdapter.authentifier(RealmAdapter.java: 418) à org.Apache.Catalina.authentificateur.FormAuthenticator.authentifier (FormAuthenticator.java: 264) à org.Apache.Catalina.authentificateur.AuthenticatorBase.processSecurityCheck (base D'authentification.java: 1015) à org.Apache.Catalina.authentificateur.AuthenticatorBase.invoke (AuthenticatorBase.java: 614) au org.Apache.Catalina.core.StandardPipeline.invoke (StandardPipeline.java: 615) au com.soleil.entreprise.Web.WebPipeline.invoke (WebPipeline.java:97) à COM.soleil.entreprise.Web.PESessionLockingStandardPipeline.invoke (PESessionLockingStandardPipeline.java: 85) à org.Apache.Catalina.core.StandardHostValve.invoke (StandardHostValve.java: 185) à org.Apache.Catalina.connecteur.CoyoteAdapter.doService (CoyoteAdapter.java: 325) au org.Apache.Catalina.connecteur.CoyoteAdapter.service (CoyoteAdapter.java: 226) à COM.soleil.entreprise.v3.service.impl.ContainerMapper.service (ContainerMapper.java: 165) à COM.soleil.Grizzly.http.ProcessorTask.invokeAdapter (ProcessorTask.java: 791) à COM.soleil.Grizzly.http.ProcessorTask.doProcess(ProcessorTask.java: 693) au com.soleil.Grizzly.http.ProcessorTask.processus(ProcessorTask.java: 954) à COM.soleil.Grizzly.http.DefaultProtocolFilter.exécuter (DefaultProtocolFilter.java: 170) à COM.soleil.Grizzly.DefaultProtocolChain.executeProtocolFilter (DefaultProtocolChain.java: 135) à COM.soleil.Grizzly.DefaultProtocolChain.exécuter (DefaultProtocolChain.java: 102) à COM.soleil.Grizzly.DefaultProtocolChain.exécuter (DefaultProtocolChain.java: 88) à COM.soleil.Grizzly.http.HttpProtocolChain.exécuter (HttpProtocolChain.java: 76) à COM.soleil.Grizzly.Protocolchaincontextextask.doCall (Protocolchaincontextask.java: 53) à COM.soleil.Grizzly.Selectionkeycontextttask.appel (SelectionKeyContextTask.java: 57) au com.soleil.Grizzly.ContextTask.run (ContextTask.java: 69) à COM.soleil.Grizzly.util.AbstractThreadPool $ Worker.doWork (AbstractThreadPool.java: 330) à COM.soleil.Grizzly.util.AbstractThreadPool $ Worker.run (AbstractThreadPool.java: 309) à java.lang.Fil.run (Thread.java: 662) causé par: javax.nommer.NamingException: échec de la recherche pour 'JDBC / security' dans SerialContext [Root exception is javax.nommer.NameNotFoundException: la sécurité non trouvé] COM.soleil.entreprise.nommer.impl.SerialContext.recherche (SerialContext.java: 442) au javax.nommer.InitialContext.recherche(InitialContext.java:392) à javax.nommer.InitialContext.recherche(InitialContext.java:392) à COM.soleil.entreprise.connecteur.service.Connectorressourceadminserviceimpl.recherche (ConnectorResourceAdminServiceImpl.java: 203) à COM.soleil.entreprise.connecteur.ConnectorRuntime.lookupNonTxResource (ConnectorRuntime.java: 440) à COM.soleil.entreprise.sécurité.auth.Royaume.jdbc.JDBCRealm.getConnection (JDBCRealm.java: 538) ... 44 plus causé par: javax.nommer.NameNotFoundException: sécurité pas trouvé à la COM.soleil.entreprise.nommer.impl.TransientContext.doLookup (TransientContext.java: 197) à COM.soleil.entreprise.nommer.impl.TransientContext.recherche (TransientContext.java: 168) à COM.soleil.entreprise.nommer.impl.TransientContext.recherche (TransientContext.java: 172) à COM.soleil.entreprise.nommer.impl.SerialContextProviderImpl.recherche (SerialContextProviderImpl.java: 58) à COM.soleil.entreprise.nommer.impl.LocalSerialContextProviderImpl.recherche (LocalSerialContextProviderImpl.java: 101) à COM.soleil.entreprise.nommer.impl.SerialContext.recherche (SerialContext.java: 430) ... 49 Plus de
amende: authentification JAAS avortée. Avertissement: l'ouverture de session Web a échoué: L'ouverture de session a échoué: javax.sécurité.auth.connexion.LoginException: Exception De Sécurité Très bien: [Web-sécurité] contexte de la Politique ID was: CHAPTER_x_12_Container_Managed_Authentication_and_authorization/CHAPTER_x_12_Container_Managed_Authentication_and_authorization Amende: [Web-sécurité] hasUserDataPermission perm: (javax.sécurité.jacc.WebUserDataPermission / error.XHTML GET) FINE: [Web-Security] hasUserDataPermission isGranted: true
Update 3
peut-être qu'il y a quelque chose de faux avec le pool de connexion. Voici à quoi ressemble ma piscine de connexion:
je n'ai pas beaucoup de propriétés, peut-être que quelque chose manque?
aussi maintenant j'ai créé une ressource JDBC, qui ressemble à ceci:
(le nom JNDI dans le royaume, a été changé en JDBC/studybd)
ma persistance.xml ressemble à ceci:
<?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>
je pense que j'ai fait quelques progrès, maintenant l'exception que je vois est:
> 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
Jour 4
j'ai changé la base de données, elle a été mal organisée donc j'ai fait quelques changements dans mes entités:
@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
@entité @Table (nom= "GROUPS", schéma = " ADMIN") public class Group implements Serialisable {
private static final long serialVersionUID = -7274308564659753174L;
@Id
@Column(nullable = false)
private String groupid;
@OneToMany(mappedBy="group")
private Set<User> users;
/ / MÉTHODES GET & SET
donc j'ai dû aussi éditer le DBRealm, maintenant il semble comme ceci:
mais quand je me connecte je reçois à nouveau une 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 /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 réponses
il manque quelques bits dans votre configuration:
- le mot de passe est enregistré en clair dans la base de données. C'est très probablement incorrect. Glassfish 3.1 utilise l'algorithme SHA-256 par défaut, de sorte que le domaine JDBC ne parviendrait pas à authentifier les utilisateurs puisque la valeur stockée dans la base de données ne correspondrait pas au condensé créé par le domaine. Vous devrez spécifier un algorithme de digestion explicite dans la configuration de realm, ou vous en remettre à la valeur par défaut. Également, vous aurez besoin de vous assurer que votre application crée les digestes quand un nouvel utilisateur est créé ou quand son mot de passe est modifié. Si vous souhaitez stocker le mot de passe en clair, vous devez spécifier la valeur "none" pour le résumé de l'algorithme.
- spécifier l'algorithme digest seul est insuffisant. Vous aurez besoin de spécifier le codage dans lequel le digest est stocké (depuis, un digest est simplement une séquence d'octets, et ne peut pas être stocké comme une séquence ASCII simple). Glassfish prend en charge l'encodage Hex et Base64, et utilise l'encodage Hex par défaut. votre application doit donc appliquer le même encodage que configuré dans le domaine, avant de stocker le digest de mot de passe. Notez que, lorsque vous spécifiez un algorithme de digest De "none" pour stocker les mots de passe en texte clair, vous n'avez pas besoin d'encoder le mot de passe stocké (et de même, vous n'avez pas besoin de spécifier un encodage non plus); au moins ceci a été mon observation de la lecture des sources de Glassfish.
- en outre, la cartographie du groupe d'utilisateurs semble être 1:1 à l'heure actuelle. vous pouvez utiliser une table de jointure séparée pour permettre des correspondances 1:N entre les groupes et les utilisateurs.
- vous devez également vous assurer que l'option" principal par défaut à la cartographie des rôles " est activée. Sans cette option, vous aurez besoin de cartographier manuellement les rôles dans le web.xml pour les utilisateurs et les groupes dans votre royaume .
sur le thème de l'utilisation de form
au lieu de h:form
, la raison sous-jacente est que L'exécution JSF ne vous permettrait pas de spécifier l'attribut action
de la balise h:form
. Cette valeur est définie par l'exécution JSF, lors de l'encodage de la réponse, et par conséquent, vous ne pourrez pas spécifier la valeur de j_security_check
lorsque vous utiliserez la balise h:form
. la documentation indique ceci très explicitement :
La valeur de l'attribut "action" doit être le résultat du passage de l' voir l'Identificateur de la vue courante de la méthode
getActionURL()
leViewHandler
pour cette application, puis passer cette chaîne à laencodeActionURL()
la méthode sur laExternalContext
.
mise à Jour
basé sur la trace affichée de la pile, je pourrais en déduire que la source de données JNDI (spécifiée dans le champ JNDI) à utiliser par le Royaume, n'est pas disponible dans Glassfish domaine. Une des conditions préalables pour le domaine JDBC est d'avoir une source de données JNDI enregistrée dans la configuration du domaine Glassfish, dont le pool de connexion est utilisé pour se connecter à la base de données sous-jacente.
ci-dessous est un extrait de mon fichier de configuration de domaine Glassfish ( domain.xml
) où un pool de connexion (GalleriaPool) est utilisé par une source de données JNDI( JDBC / galleriaDS), qui est éventuellement utilisé par le domaine 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>
mise à Jour #2 - Obtenir les instructions SQL exécutées par le JDBC Royaume contre Derby
il semble que la structure de la requête SQL ne correspond pas au modèle de base de données que vous avez préparé. Vous pouvez jeter un oeil aux déclarations SQL exécutées par le Royaume JDBC contre l'instance de Derby via la propriété système derby.language.logStatementText
. Cette propriété peut être définie à true
comme valeur statique dans le fichier derby.properties
, et il prendra effet lorsque vous redémarrez l'instance de Derby. Le fichier derby.properties
doit comporter la mention suivante:
derby.language.logStatementText=true
et ce fichier doit être placé dans le répertoire courant de l'instance du Derby. Le répertoire de travail courant est souvent le répertoire qui contient les bases de données Derby, et peut être spécifié explicitement en utilisant l'argument derby.system.home
JVM, lors du démarrage de Derby:
-Dderby.system.home=C:\derby
toutes les instructions SQL exécutées par Derby seront désormais enregistrées dans le fichier derby.log
.
sur la base des informations fournies, j'ai l'impression qu'il existe une table séparée appelée GROUPS
qui est utilisée pour stocker les informations du groupe, et c'est différent de la table de jointure - USER_GROUP
. Dans ce scénario, votre domaine doit être configuré pour avoir la table de groupe comme USER_GROUP
et non GROUP
; vous pouvez confirmez ceci en regardant les requêtes SQL émises par le domaine JDBC.
pour clarifier le point ci-dessus, le champ Group dans la configuration du domaine JDBC n'est pas utilisé pour spécifier la table qui stocke les informations du groupe. Au lieu de cela, il est utilisé pour spécifier la table qui stocke le groupe-User mappings. Dans un mapping 1:1, la table de groupe peut stocker cette information, mais dans un 1:M ou typiquement dans un scénario M:M, vous auriez une table séparée qui contient la mapping. SQL la requête émise par le domaine JDBC, utilise la table de correspondance et non la table de groupe réelle (si elles sont différentes) pour déterminer les groupes auxquels un utilisateur appartient.
en plus de la réponse de Vineet , j'ai aussi remarqué que l'option security Manager n'est pas cochée dans L'onglet Security de GlassFish, cette option devrait être activée afin d'utiliser la sécurité dans votre Royaume.
autre chose si vous utilisez un nom JDBC JNDI vous n'avez pas besoin de fournir un nom d'utilisateur/mot de passe pour le domaine JDBC
j'ai déjà fait cela sur Sailfin (basé sur Glassfish 2).
D'abord, je ne vois pas de sun-web.fichier xml qui établit la correspondance entre les rôles définis dans votre site web.fichier xml pour les groupes définis de la base de données.
Second, selon ce tutoriel: http://codepimpsdotorg.blogspot.com/2007/12/glassfish-jdbc-realm-authentication.html vous devez spécifier un algorithme de digest ("none" n'est pas une option, pas sûr si elle reste la même dans Glassfish 3).
Troisièmement, les tableaux et les colonnes doivent être dans un ordre particulier, nous utilisons la structure suivante:
@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;
...
et
@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;
...
et de définir le Royaume:
user-table=AuthenticationUser
user-name-column=name
password-column=password
group-table=AuthenticationUser
group-name-column=groupName
IMPORTANT: le nom d'utilisateur et le nom de groupe appartiennent à la même table! ainsi la table AuthenticationGroup est seulement pour notre usage interne, mais n'est pas utilisée par Glassfish.
j'ai rencontré le même problème.
j'ai résolu ce problème en renommant le mot de passe en(User_password) et les champs de nom d'utilisateur (User_name) dans la table (n'importe quoi d'autre que le nom d'utilisateur et le mot de passe fera), d'une manière ou d'une autre en utilisant" userName "et" password " provoque un certain conflit tout en effectuant l'authentification en utilisant des Realms.
met aussi L'algorithme Digest: = aucun dans le cas où vous stockez le mot de passe en texte simple.
dans la sécurité menu, Active le principe par défaut à la cartographie des rôles.
Espère que cette aide,