Я хочу создать страницу Spring с URL-адресом
http://myapp.com/[email protected]&pw=пароль
password
— это одноразовый пароль, который пользователь получает по электронной почте каждый раз, когда хочет войти в систему.
Всякий раз, когда пользователь посещает эту страницу, я хочу, чтобы произошли две вещи:
Я сделал первую часть:
@Autowired
private var userRepository: UserRepository? = null
@GetMapping
fun signIn(@RequestParam email:String, @RequestParam(name = "pw") password:String): RedirectView {
// Is the password correct?
// TODO: Read password hash of the user
val existingUser: Optional<UserInfo>? = userRepository?.findById(email)
if (existingUser == null) {
return redirectToErrorPage("Please register with your e-mail address first")
}
if (!existingUser.isPresent) {
return redirectToErrorPage("Please register with your e-mail address first")
}
val hashInDb = existingUser.get().passwordHash
val hashInParam = PasswordHashCalculator.calculateHash(password)
if (!hashInDb.equals(hashInParam)) {
return redirectToErrorPage("Invalid user name and/or password")
}
// TODO: Display the main page
return null
}
Как мне изменить код, чтобы отображалась главная страница (HTML-файл в src/main/resources/static
), но только при условии прохождения аутентификационных проверок?
Обновление 1: Использование return ClassPathResource("main.html")
в соответствии с рекомендациями здесь не помогло.
Вы не должны так заботиться о своей безопасности. Не рекомендуется отправлять пароль открытым текстом через http.
Здесь есть примеры базовой аутентификации с Spring Security.
https://www.baeldung.com/spring-security-basic-authentication
https://www.baeldung.com/securing-a-restful-web-service-with-spring-security
Что вы можете сделать, если вы будете следовать этому руководству, так это назначить пользователя в памяти для начала. Затем вы можете Base64Encode свои данные аутентификации для пользователя. Затем для каждого пользователя вы можете отправить данные аутентификации, и никто не сможет отследить имя пользователя и пароль, когда они проходят по проводу, и ваш запрос обрабатывается до того, как он достигнет вашего контроллера. Таким образом, вы можете отделить свою бизнес-логику от аутентификации.
Это хотя бы начало. Надеюсь это поможет.
Не могли бы вы рассказать о своих причинах, чтобы мы могли помочь вам в дальнейшем? На самом деле не следует реализовывать безопасность Spring таким образом по какой-либо причине. Если вам абсолютно необходимо сделать это таким образом, вы можете использовать Controller Advice, чтобы генерировать исключение каждый раз, когда вам предоставляется неправильный пароль. Как вы проверяете свой пароль, зависит от вас, хотя база данных или что-то еще. Чтобы вернуться после успешной проверки веб-страницы, верните «index.html» или любую другую страницу, которую вы хотите, и это будет служить вам вашей страницей.
Причина в том, что я хочу создать максимально простой прототип. Было бы идиотизмом тратить много времени на разработку сложной системы безопасности, возиться с проблемами безопасности Spring, если ваша программа работает только на вашей локальной машине. Для моих целей ток достаточно аутентификации по электронной почте.
@RobScully прав, вы не должны обрабатывать авторизацию таким образом. Что вы можете сделать, так это включить spring-security и использовать аннотации безопасности Spring для обработки этого сценария. Используйте следующие зависимости и настройте базовую настройку безопасности Spring.
Такие аннотации, как @PreAuthorize()
, можно использовать для проверки привилегий пользователя перед выполнением метода. Вы даже можете добавить эту аннотацию к методам контроллера для проверки перед обслуживанием каждого запроса, если вы настаиваете.
Вы можете настроить и LDAP-сервер или Oauth или даже использовать база данных для аутентификации (если вы работаете над демонстрацией или чем-то еще).
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring-security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring-security.version}</version>
</dependency>
Используйте класс конфигурации, как показано ниже, для настройки безопасности:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
DataSource dataSource;
@Autowired
public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth.jdbcAuthentication().dataSource(dataSource)
.usersByUsernameQuery(
"select username,password, enabled from users where username=?")
.authoritiesByUsernameQuery(
"select username, role from user_roles where username=?");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')") //To check admin role permission
.and()
.formLogin().loginPage("/login").failureUrl("/login?error") //provide failure url
.usernameParameter("username").passwordParameter("password")
.and()
.logout().logoutSuccessUrl("/login?logout")
.and()
.exceptionHandling().accessDeniedPage("/403")
.and()
.csrf();
}
}
Этот пример проекта в github дает базовую настройку, в которой вы можете использовать Spring Security:
https://github.com/mohchi/spring-security-request-mapping
Справочное использование: https://www.mkyong.com/spring-security/spring-security-form-login-using-database/
return ClassPathResource("static/main.html") should answer your question, don't forget to specify `static` folder at the beginning as `ClassPathResource` points to the `resources` folder
Я хочу реализовать аутентификацию таким образом по какой-то причине. Речь идет об условном отображении статического контента, а не об изменении подхода к безопасности.