#spring #spring-boot #authentication #access-token
#spring #spring-boot #аутентификация #токен доступа
Вопрос:
Мне нужно предоставить логин пользователя с помощью приложения SpringBoot.
Запрос пользователя на вход в систему будет представлять собой запрос Rest, полезная нагрузка которого состоит из «имени пользователя» и «пароля».
Мне нужно сначала проверить эти учетные данные из базы данных и сгенерировать токен, действительный в течение определенного времени. Затем после входа в систему все последующие запросы будут иметь этот токен, и этот токен будет проверяться каждый раз.
Я выполнил часть проверки токена, но я действительно запутался при первом входе в систему, я понятия не имею, как это сделать.
Даже при первом запросе на вход в систему система будет проверять аутентификацию по токену, которая, очевидно, завершается неудачей.
Я хочу, чтобы система просто сгенерировала токен в первый раз после проверки имени и пароля из базы данных.
Я впервые внедряю вход пользователя в систему с помощью Spring Boot Security, поэтому я довольно невежествен в этом. Хотя я много исследовал и читал онлайн, но все еще не смог разобраться в этой части.
- Редактировать:
Ниже приведен класс конфигурации безопасности, который расширяет WebSecurityConfigurerAdapter
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(getPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.cors().and().csrf().disable();
http.authorizeRequests()
.antMatchers("/","**/firstPage").authenticated()
.anyRequest().permitAll()
.and()
.formLogin().loginPage("/login").
permitAll()
.and().logout().permitAll();
}
Ниже приведен запрос, который будет вызван после входа в систему.Как аутентифицировать пользователя в нем, используя уже сгенерированный токен? Токен отправляется в заголовке запроса.
@PostMapping(value = "/home")
public ResponseEntity<ConsolidateResponse> TestReques(@RequestBody TestParam testParam)
throws Exception {
//Some logic
}
Комментарии:
1. В принципе, для конечной точки входа в систему вы должны разрешить запрос без авторизации. Это можно сделать в вашем классе конфигурации веб-безопасности, который расширяет
WebSecurityConfigurerAdapter
2. Если вы можете добавить свой класс конфигурации веб-безопасности (тот, который расширяется
WebSecurityConfigurerAdapter
), я могу указать вам, как вы можете это сделать.3. @MadhuBhat После отключения аутентификации по умолчанию, как приложение будет проверять подлинность всех запросов, следующих за запросом входа в систему? и как тогда обрабатывать истечение срока действия токена?
4. Аутентификация будет отключена только на конечной точке входа, а не на остальных конечных точках. Если вы можете показать код, который вы уже пробовали, я могу вам помочь.
5. @MadhuBhat Я обновил свой вопрос. Теперь у вас будет более четкая картина. Пожалуйста, дайте мне знать, как аутентифицировать последующие запросы.
Ответ №1:
Если вы отключите форму входа в систему из класса конфигурации spring security и предоставите одну конечную точку rest (/auth), вы сможете обрабатывать вход в систему и генерировать токен.Здесь я использовал jwt для генерации токена.
@RequestMapping(value = "/auth", method = RequestMethod.POST)
public ResponseEntity<?> createAuthenticationToken(@RequestBody JwtAuthenticationRequest authenticationRequest) throws AuthenticationException, IOException {
// Perform the security
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
authenticationRequest.getUsername(), authenticationRequest.getPassword());
final Authentication authentication = authManager.authenticate(token);
if (!authentication.isAuthenticated()) {
throw new BadCredentialsException("Unknown username or password");
}
// Reload password post-security so we can generate token
final UserDetails userDetails = userDetailsService.loadUserByUsername(authenticationRequest.getUsername());
final String jwtoken = jwtTokenUtil.generateToken(userDetails);
return ResponseEntity.ok(responseBean);
}
При использовании аутентификации без состояния мы можем явно передать параметр token контроллеру и подтвердить его.В случае, если включена аутентификация на основе сеанса, мы также можем использовать @AuthenticationPrincipal
for для извлечения текущего зарегистрированного пользователя.
//Stateless authentication
@PostMapping(value = "/home")
public ResponseEntity<ConsolidateResponse> test(@RequestBody TestParam testParam,String token)
throws Exception {
Boolean isValidToken = jwtTokenUtil.validateToken(token);
if(isValidToken) {
//Some logic
}else {
//invalid request
}
}
@PostMapping(value = "/home")
public ResponseEntity<ConsolidateResponse> test(@RequestBody TestBean requestToken,
@AuthenticationPrincipal User contextPrincipal, HttpServletRequest req) {
Optional.ofNullable(contextPrincipal).orElseThrow(InvalidUserSession::new);
//some logic
}
Комментарии:
1. Будет ли этот метод обрабатывать аутентификацию для последующих запросов и истечение срока действия токена?
2. @Just_another_developer этот метод предназначен для входа в систему и генерации токена. Для проверки истечения срока действия токена или того, что этот пользователь вошел в систему, вы можете просто добавить параметр токена в конечную точку «/ home» и подтвердить токен. Я обновлю свой ответ вкратце
3. спасибо за вашу помощь, у меня есть путаница, хотя, если у кого-то есть этот токен, они могут получить доступ к приложению даже без входа в систему, это правда? допустим, я создаю токен с истечением срока действия в один день, а какие-то хакеры перехватывают запрос и получают токен, теперь они могут получить доступ к приложению, даже не пройдя проверку подлинности. верно?
4. Да, если у кого-то есть действительный токен, то для него будут доступны ресурсы. Вы можете обезопасить трафик с помощью https.