#java #spring #spring-mvc #spring-security
#java #spring #spring-mvc #spring-безопасность
Вопрос:
Rememberconfigurer использует UserDetailsService, вызывая свой метод loadUserByUsername(), проблема в том, что я хочу, чтобы он передавал адрес электронной почты пользователя, а не имя пользователя. Он работает с простым входом в систему, но не с опцией запомнить меня. Как я могу заставить функцию запоминания меня передавать электронную почту (не имя пользователя) в UserDetailsService.loadUserByUsername()? форма входа:
<form action="login" method="POST" >
<legend>Sing In</legend>
<div class="form-group">
<div class="input-group">
<label class="form-label" for="email">
Email
</label>
<div class="form-input-field">
<input id="email" name="username"
type="text" autocomplete="off"/>
</div>
</div>
</div>
<div class="form-group">
<div class="input-group">
<label class="form-label" for="password">
Password
</label>
<div class="form-input-field">
<input id="password" name="password"
type="password" autocomplete="off" />
</div>
</div>
</div>
<div class="form-group">
<div class="input-group">
<label id="checkbox-label" class="form-label" for="remember">
Remember me
</label>
<div class="form-input-field">
<input id="remember" name="remember"
type="checkbox" />
</div>
</div>
<div id="submit-button">
<input type="submit" value="Sign In" />
</div>
</form>
Настройка WebSecurityConfiguration:
@Override
public void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.formLogin()
.loginPage("/login")
.permitAll()
.defaultSuccessUrl("/account")
.and()
.rememberMe()
.key("rem-me-key")
.userDetailsService(userDetailsService)
.rememberMeParameter("remember")
.rememberMeCookieName("rememberMeCookie")
.tokenValiditySeconds(60 * 60 * 24 * 3)
.and()
.logout()
.deleteCookies("JSESSIONID")
.permitAll();
httpSecurity.authorizeRequests()
.mvcMatchers("/admin").hasRole("ADMIN")
.mvcMatchers("/account").hasRole("CUSTOMER")
.mvcMatchers("/cart").hasRole("CUSTOMER")
.anyRequest().permitAll();
httpSecurity.csrf()
.disable();
}
UserDetailsService impl:
@Service
public class AppUserDetailsService implements UserDetailsService {
private static final Logger log =
LogManager.getLogger(AppUserDetailsService.class.getName());
private AppUserRetrievalRepository appUserRetrievalRepository;
public AppUserDetailsService(
@Autowired
AppUserRetrievalRepository appUserRetrievalRepository) {
this.appUserRetrievalRepository = appUserRetrievalRepository;
}
@Override
public UserDetails loadUserByUsername(String email)
throws UsernameNotFoundException {
log.info("Trying to load user by name: " email);
Optional<AppUser> optUser =
appUserRetrievalRepository.getUserByEmail(email);
UserDetails userDetails =
new AppUserDetails(optUser.orElseThrow(
() -> new UsernameNotFoundException(email " cannot be found") )
);
return userDetails;
}
}
Журналы, показывающие проблему:
~ Когда я использую логин без отмеченной опции запомнить меня:
*** LOG4J *** Trying to load user by name: myEmailAddress@example.com
~ Когда я использую логин с проверенной опцией запомнить меня:
*** LOG4J *** Trying to load user by name: cody
Комментарии:
1.
I want it to pass user's email and not username. It works with simple login, but not with remember me option.
Я не понимаю вашего вопроса. Пожалуйста, напишите более подробно, с журналами отладки, которые показывают проблему.2. Таким образом, адрес электронной почты является именем пользователя, и ваша
UserDetails
реализация должна отражать это.3. Я так и сделал. Если я правильно понял, проблема в том, что после успешной аутентификации RememberMeConfigurer использует метод loadByUsername() для получения пользователя и создания файла cookie. Было бы хорошо, если бы он передавал электронную почту (myEmailAddress@example.com ), но он передает имя пользователя (cody).
4. Потому что, я полагаю, что ваш
AppUserDetails
не возвращает адрес электронной почты должным образом в качестве имени пользователя, которое оно должно.5. Да, это сработало. Спасибо, М. Дейнум!