La Configuration De Spring Security 3.x d'avoir plusieurs points d'entrée
J'ai été en utilisant le Printemps de Sécurité 3.x pour gérer l'authentification des utilisateurs pour mes projets, et jusqu'à présent, il a travaillé à la perfection.
J'ai récemment reçu les exigences pour un nouveau projet. Dans ce projet, il nécessite 2 ensembles d'authentification de l'utilisateur: l'un pour l'authentification des employés contre LDAP, et un autre pour authentifier le client à l'encontre de la base de données. Je suis un peu perplexe sur la façon de configurer que dans le Printemps de Sécurité.
Mon idée initiale était de créer un écran de connexion qui a les champs suivants:-
- bouton radio de champ pour les utilisateurs de choisir s'ils sont des employés ou des clients.
j_username
champ utilisateur.j_password
champ mot de passe.
Si l'utilisateur sélectionne "employé", alors je veux le Printemps de Sécurité pour authentifier leur contre LDAP, sinon les informations d'identification seront authentifiés à l'aide de la base de données. Cependant, le problème est le formulaire sera soumis à /j_spring_security_check
et il n'y a aucun moyen pour moi d'envoyer le bouton radio de domaine à mon mis en œuvre fournisseur d'authentification personnalisé. Ma première pensée est que j'ai probablement besoin de deux formulaire de soumission d'Url plutôt que de compter sur la valeur par défaut /j_spring_security_check
. Chaque URL seront traitées par les différents fournisseurs d'authentification, mais je ne suis pas sûr de savoir comment configurer que dans le Printemps de Sécurité.
Je sais que dans le Printemps de Sécurité, je peux configurer l'automne dos l'authentification, par exemple si l'authentification LDAP échoue, alors il reviendra à l'authentification de base de données, mais ce n'est pas ce que je suis en tournage pour dans ce nouveau projet.
Quelqu'un peut-il partager exactement comment je dois configurer le Printemps de Sécurité 3.x?
Merci.
Mise à JOUR - 01-28-2011 - @EasyAngel la technique de
Je suis en train de faire ce qui suit:-
- Employé formulaire de connexion se soumet à
/j_spring_security_check_for_employee
- Client formulaire de connexion se soumet à
/j_spring_security_check_for_customer
La raison pour laquelle je veux 2 forme différente de connexions est de me permettre de gérer l'authentification différemment, en fonction de l'utilisateur, au lieu de faire un repli de l'authentification. Il est possible que les employés et les clients ont le même ID d'utilisateur, dans mon cas.
J'ai incorporé @EasyAngel de l'idée, mais d'avoir à les remplacer certains obsolète classes. Le problème, je suis actuellement confronté à est ni filtre processus URL semblent inscrits dans le Ressort de Sécurité parce que je reçois des Error 404: SRVE0190E: File not found: /j_spring_security_check_for_employee
. Mon sentiment profond est le springSecurityFilterChain
haricot n'est pas câblé correctement, donc mes filtres personnalisés ne sont pas utilisés.
Par le chemin, je suis à l'aide de WebSphere et j'ai com.ibm.ws.webcontainer.invokefilterscompatibility=true
propriété définie dans le serveur. Je suis en mesure de frapper la valeur par défaut /j_spring_security_check
sans problème.
Voici ma configuration de sécurité:-
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:sec="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
<sec:http auto-config="true">
<sec:form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?login_error=1" default-target-url="/welcome.jsp"
always-use-default-target="true" />
<sec:logout logout-success-url="/login.jsp" />
<sec:intercept-url pattern="/employee/**" access="ROLE_EMPLOYEE" />
<sec:intercept-url pattern="/customer/**" access="ROLE_CUSTOMER" />
<sec:intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY" />
</sec:http>
<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy">
<sec:filter-chain-map path-type="ant">
<sec:filter-chain pattern="/**" filters="authenticationProcessingFilterForEmployee, authenticationProcessingFilterForCustomer" />
</sec:filter-chain-map>
</bean>
<bean id="authenticationProcessingFilterForEmployee" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManagerForEmployee" />
<property name="filterProcessesUrl" value="/j_spring_security_check_for_employee" />
</bean>
<bean id="authenticationProcessingFilterForCustomer" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManagerForCustomer" />
<property name="filterProcessesUrl" value="/j_spring_security_check_for_customer" />
</bean>
<bean id="authenticationManagerForEmployee" class="org.springframework.security.authentication.ProviderManager">
<property name="providers">
<list>
<ref bean="employeeCustomAuthenticationProvider" />
</list>
</property>
</bean>
<bean id="authenticationManagerForCustomer" class="org.springframework.security.authentication.ProviderManager">
<property name="providers">
<list>
<ref bean="customerCustomAuthenticationProvider" />
</list>
</property>
</bean>
<bean id="employeeCustomAuthenticationProvider" class="ss.EmployeeCustomAuthenticationProvider">
<property name="userDetailsService">
<bean class="ss.EmployeeUserDetailsService"/>
</property>
</bean>
<bean id="customerCustomAuthenticationProvider" class="ss.CustomerCustomAuthenticationProvider">
<property name="userDetailsService">
<bean class="ss.CustomerUserDetailsService"/>
</property>
</bean>
<sec:authentication-manager>
<sec:authentication-provider ref="employeeCustomAuthenticationProvider" />
<sec:authentication-provider ref="customerCustomAuthenticationProvider" />
</sec:authentication-manager>
</beans>
Je commence un bounty ici parce que je n'arrive pas à obtenir ce travail pendant plusieurs jours déjà... la frustration est le mot. J'espère que quelqu'un va remarquer le problème(s), ou si vous pouvez me montrer un mieux ou plus propre façon de gérer cela (dans le code).
Je suis en utilisant le Printemps de Sécurité 3.x.
Merci.
Mise à JOUR 01-29-2011 - @Ritesh la technique de
Bon, j'ai réussi à obtenir @Ritesh de l'approche du travail de très près à ce que je voulais. J'ai la case d'option qui permet à l'utilisateur de sélectionner qu'ils soient clients ou employés. Il semble que cette approche fonctionne assez bien, avec un problème...
- Si l'employé se connecte avec droit de justificatif d'identité, ils sont autorisés dans... fonctionner COMME PRÉVU.
- Si l'employé se connecte avec de mauvaises informations d'identification, ils ne sont pas autorisés dans... fonctionner COMME PRÉVU.
- Si le client se connecte avec droit de justificatif d'identité, ils sont autorisés dans... fonctionner COMME PRÉVU.
- Si le client se connecte avec de mauvaises informations d'identification, l'authentification retombe à l'employé d'authentification... NE fonctionne PAS. C'est risqué parce que si je sélectionne une authentification client, et le coup de poing de l'employé d'informations d'identification, il permettra à l'utilisateur de trop et ce n'est pas ce que je veux.
<sec:http auto-config="false" entry-point-ref="loginUrlAuthenticationEntryPoint">
<sec:logout logout-success-url="/login.jsp"/>
<sec:intercept-url pattern="/employee/**" access="ROLE_EMPLOYEE"/>
<sec:intercept-url pattern="/customer/**" access="ROLE_CUSTOMER"/>
<sec:intercept-url pattern="/**" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
<sec:custom-filter position="FORM_LOGIN_FILTER" ref="myAuthenticationFilter"/>
</sec:http>
<bean id="myAuthenticationFilter" class="ss.MyAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationFailureHandler" ref="failureHandler"/>
<property name="authenticationSuccessHandler" ref="successHandler"/>
</bean>
<bean id="loginUrlAuthenticationEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
<property name="loginFormUrl" value="/login.jsp"/>
</bean>
<bean id="successHandler"
class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
<property name="defaultTargetUrl" value="/welcome.jsp"/>
<property name="alwaysUseDefaultTargetUrl" value="true"/>
</bean>
<bean id="failureHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
<property name="defaultFailureUrl" value="/login.jsp?login_error=1"/>
</bean>
<bean id="employeeCustomAuthenticationProvider" class="ss.EmployeeCustomAuthenticationProvider">
<property name="userDetailsService">
<bean class="ss.EmployeeUserDetailsService"/>
</property>
</bean>
<bean id="customerCustomAuthenticationProvider" class="ss.CustomerCustomAuthenticationProvider">
<property name="userDetailsService">
<bean class="ss.CustomerUserDetailsService"/>
</property>
</bean>
<sec:authentication-manager alias="authenticationManager">
<sec:authentication-provider ref="customerCustomAuthenticationProvider"/>
<sec:authentication-provider ref="employeeCustomAuthenticationProvider"/>
</sec:authentication-manager>
</beans>
Voici ma configuration mise à jour. Il doit être vraiment petit tweak-je faire pour empêcher l'authentification de tomber en arrière, mais je n'arrive pas à le comprendre maintenant.
Merci.
Mise à JOUR de la SOLUTION de @Ritesh la technique de
Bon, je pense avoir résolu le problème ici. Au lieu d'avoir EmployeeCustomAuthenticationProvider
de s'appuyer sur la valeur par défaut UsernamePasswordAuthenticationToken
, j'ai créé EmployeeUsernamePasswordAuthenticationToken
pour elle, tout comme celui que j'ai créé CustomerUsernamePasswordAuthenticationToken
pour CustomerCustomAuthenticationProvider
. Ces fournisseurs seront ensuite remplacer le supports()
:-
CustomerCustomAuthenticationProvider classe
@Override
public boolean supports(Class<? extends Object> authentication) {
return (CustomerUsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
}
EmployeeCustomAuthenticationProvider classe
@Override
public boolean supports(Class<? extends Object> authentication) {
return (EmployeeUsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication));
}
MyAuthenticationFilter classe
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
...
UsernamePasswordAuthenticationToken authRequest = null;
if ("customer".equals(request.getParameter("radioAuthenticationType"))) {
authRequest = new CustomerUsernamePasswordAuthenticationToken(username, password);
}
else {
authRequest = new EmployeeUsernamePasswordAuthenticationToken(username, password);
}
setDetails(request, authRequest);
return super.getAuthenticationManager().authenticate(authRequest);
}
... et WALAA! Il fonctionne parfaitement maintenant, après plusieurs jours de frustration!
J'espère que ce post pourra aider quelqu'un qui est en train de faire la même chose que je suis ici.
- vous pouvez également prévenir les secours en jetant l'exception de fournisseur et de l'attraper dans le filtre. Le prochain fournisseur dans la chaîne est consulté uniquement lorsqu'un fournisseur renvoie la valeur null.
- merci! Je suppose que j'ai des connaissances limitées sur la Sécurité Printemps et pendant tout ce temps, j'ai été en utilisant la méthode la plus simple et la plus simple de configuration, mais je ne peux pas faire de même pour ce nouveau projet. Mais, c'est une bonne expérience d'apprentissage, en dehors de toute la douleur que j'ai vécu. 🙂 Pour l'instant, je crois que je préfère le à l'aide de la
support()
au lieu de les jeter exception de fournisseur car je crois que c'est le plus propre approche. - Post la solution, une réponse, s'il vous plaît, et de l'accepter, si vous le souhaitez. De cette façon, les gens vont voir immédiatement qui est la solution. 😉
Vous devez vous connecter pour publier un commentaire.
Vous n'avez pas besoin de créer
/j_spring_security_check_for_employee
et/j_security_check_for_customer
filterProcessingUrl
.La valeur par défaut fonctionne très bien avec bouton radio champ idée.
Dans la coutume de connexion
LoginFilter
, vous avez besoin pour créer des jetons différents pour les employés et les clients.Voici les étapes:
Utiliser la valeur par défaut
UsernamePasswordAuthenticationToken
pour les employés de connexion.Créer
CustomerAuthenticationToken
pour la connexion du client. ÉtendreAbstractAuthenticationToken
de sorte que sa classe est de type distinct deUsernamePasswordAuthenticationToken
.Définir une connexion personnalisée filtre:
Dans
customFormLoginFilter
, remplacerattemptAuthentication
comme suit (pseudo-code):Remplacer
supports
méthode dansEmployeeCustomAuthenticationProvider
à l'appui deUsernamePasswordAuthenticationToken
.Remplacer
supports
méthode dansCustomerCustomAuthenticationProvider
à l'appui deCustomerAuthenticationToken
.Utiliser à la fois des fournisseurs de
authentication-manager
:customFormLoginFilter
étendreUsernamePasswordAuthenticationFilter
? J'ai peur que si ce filtre implémenteUsernamePasswordAuthenticationFilter
, je vais avoir le "deux filtres dans le même ordre d '" exception comme décrit dans ma réponse à @EasyAngel. Pouvez-vous expliquer pourquoi #6 doit remplacersupport()
mais #5 n'a pas besoin d'?Vous pouvez définir plusieurs
AuthenticationProcessingFilter
filtres. Chacun d'eux peut avoir différentes URL comme /j_security_check_for_employee et /j_security_check_for_customer. Ici est un exemple de l'application de sécurité contexte qui illustre cette idée:Comme vous pouvez le voir, dans ce scénario, vous avez également différents
UserDetailService
s - pour DB auth LDAP.Je pense que c'est une bonne idée d'avoir différents auth Url pour les clients et les employés (en particulier si elles utilisent différentes stratégies d'authentification). Vous pouvez même avoir différentes pages d'ouverture de session pour eux.
authenticationProcessingFilterForEmployee
ne sera pas utilisé et un seul auth mécanisme a lieu./*
). 2) déconnexion est simple: tout ce que vous devez faire - est d'invalider la session comme ceci:request.getSession().invalidate()
(c'est totalement indépendant du type de connexion)Vous pouvez stocker ces informations dans la base de données. Vous pouvez par exemple colonne appelée
ldap_auth
dansUsers
table. Vous pouvez regarder mes autres réponses (par exemple):Printemps formulaire de connexion exemple
Si vous regardez bien
UserService
classe, vous remarquerez que j'ai fait tester cette LDAP drapeau et de prendre de l'utilisateur mot de passe à partir de LDAP ou une base de données.c'est encore moi 🙂 Pouvez-vous essayer d'utiliser des filtres comme ceci:
au lieu de définir le haricot
springSecurityFilterChain
.springSecurityFilterChain
et d'ajouter ces 2 lignes, et j'obtiens les erreurs suivantes:Configuration problem: Filter beans '<authenticationProcessingFilterForEmployee>' and '<authenticationProcessingFilterForCustomer>' have the same 'order' value. When using custom filters, please make sure the positions do not conflict with default filters. Alternatively you can disable the default filters by removing the corresponding child elements from <http> and avoiding the use of <http auto-config='true'>.
auto-config
àfalse
et j'obtiens toujours cette erreur. Je pense que c'est parce que à la fois des employés et des clientsUsernamePasswordAuthenticationFilter
. J'ai essayé de créer mon filtre personnalisé qui étend le champ de filtre, et j'obtiens la même erreur de trop.<sec:custom-filter ref="authenticationProcessingFilterForCustomer" position="FIRST"/>
(position
au lieu deafter
)BeanDefinitionParser
et a trouvé que l'ordre du filtre est affecté là. Selon le XSD (springframework.org/schema/security/spring-security-3.1.xsd) vous pouvez placer des filtres dansposition
,before
,or after
certains de filtre nommé (valeurs possibles peuvent être trouvées dans simpleTypenamed-security-filter
). Pour le faire fonctionner, vous pouvez essayer de placer ces 2 filtre (ou avant/après) différents filtres nommés (je les ai placés à la foisFIRST
position, mais il semble que c'est faux).org.springframework.security.config.http.HttpSecurityBeanDefinitionParser
dans la méthodebuildCustomFilterList
- peut-être, vous trouverez la solution du problème. Je peux aussi vous recommandons d'essayer de déboguer l'application pendant la sturtup et essayer de savoir pourquoi les deux filtres de recevoir le même ordre, même si vous avez placé dans différents emplacements. (J'ai même ne me souviens pas combien d'heures j'ai passé à passé de débogage printemps-sécurité, mais il a été très utile. J'ai appris beaucoup de choses sur elle)