J'utilise la sécurité de printemps dans mon MVC code> MVC code>
JDBCUSERDétailsManager code> est initialisé avec la requête suivante pour l'authentification: P>
select u.username, a.authority from user u join authority a on u.userId = a.userId where username = ?
6 Réponses :
Vous pouvez définir des requêtes personnalisées dans
Utilisateurs-by-username-Nom de nom code> et
autorités-by-userername-requête code> attributs respectivement.
<jdbc-user-service data-source-ref="" users-by-username-query="" authorities-by-username-query=""/>
C'est exactement ce que je fais déjà et je les ai inclus dans ma question. La question est que je dois les personnaliser pour inclure à la fois le nom d'utilisateur et le courrier électronique.
Vous n'avez pas mentionné que vous savez comment les configurer. Et vous demandez «existe-t-il un moyen de modifier ces deux requêtes pour atteindre cela?».
Malheureusement, il n'y a pas de moyen facile de le faire juste en changeant les requêtes. Le problème est que la sécurité du printemps s'attend à ce que les utilisateurs-by-username-Nom d'utilisateur et les autorités-Nom d'utilisateur ont un seul paramètre (nom d'utilisateur), donc si votre requête contient deux paramètres tels que
<authentication-manager> <authentication-provider user-service-ref='myUserDetailsService'/> </authentication-manager> <beans:bean id="myUserDetailsService" class="xxx.yyy.UserDetailsServiceImpl"> </beans:bean>
J'ai regardé la classe mais j'ai un peu de difficulté à comprendre quelles méthodes dois-je écraser. Des pointeurs?
Je pense que je le vois maintenant: LockUserByAusername (Nom d'utilisateur String)
Si j'ai bien compris cela correctement, le problème est que vous souhaitez rechercher le nom d'utilisateur d'utilisateur saisi par l'utilisateur dans deux colonnes DB différentes.
Bien sûr, vous pouvez le faire en personnalisant userDétailsService. p>
select username, password, enabled from user where (username = ? or email = ?) select u.username, a.authority from user u join authority a on u.userId = a.userId where (username = ? or email = ?)
J'ai eu le même problème, et après avoir essayé de nombreuses questions différentes, avec des procédures ... j'ai constaté que cela fonctionne:
public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception { // Codificación del hash PasswordEncoder pe = new BCryptPasswordEncoder(); String userByMailQuery = "SELECT mail, password, enabled FROM user_ WHERE mail = ?;"; String userByUsernameQuery = "SELECT mail, password, enabled FROM user_ WHERE username=?"; String roleByMailQuery = "SELECT mail, authority FROM role WHERE mail =?;"; auth.jdbcAuthentication().dataSource(dataSource).passwordEncoder(pe) .usersByUsernameQuery(userByMailQuery) .authoritiesByUsernameQuery(roleByMailQuery); auth.jdbcAuthentication().dataSource(dataSource).passwordEncoder(pe) .usersByUsernameQuery(userByUsernameQuery) .authoritiesByUsernameQuery(roleByMailQuery); }
Voici une solution de contournement que j'ai découverte. Fondamentalement, je suis concaténant nom d'utilisateur et adresse e-mail avec un caractère délimiteur entre (par exemple 'jsmith~johnsmith@gmail.com'), et vérifiez si le paramètre correspond si le paramètre correspond à la gauche du délimiteur ou correspond à la partie droite de Le délimiteur: Si vous craignez que le caractère de délimiteur (tel que ~) puisse exister dans le nom d'utilisateur ou par courrier électronique, utilisez plutôt un caractère de délimiteur non standard (par exemple, X'9C ') p> p>
Vous pouvez utiliser votre utilisateurdetailservice.et config, comme le code ci-dessous.
@Service public class MyUserDetailsService implements UserDetailsService { @Override public UserDetails loadUserByUsername(String usernameOrEmail) throws UsernameNotFoundException { var user = /** here search user via jpa or jdbc by username or email **/; if(user == null ) throw new UsernameNotFoundExeption(); else return new UserDetail(user); // You can implement your user from UserDerail interface or create one; } }