Вход в систему Spring Security REST

У меня возник вопрос о входе в систему с помощью REST API с Spring Security. Поскольку вход в систему с окном входа по умолчанию, предоставленным Spring Security, работает и аутентифицируется с помощью базы данных, я понятия не имею, как сделать свой собственный вход в систему. Я знаю, как подставить форму на свою, но куда отправлять данные? Должен ли я отправить его по какому-то адресу? Я сделал базовую форму с именем пользователя и паролем.

0
0
5 965
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете хранить имена пользователей и пароли в базе данных, которые вы можете использовать для входа пользователей. Вы создаете свой собственный класс, который расширяет WebSecurityConfigurerAdapter и переопределяет методы, которые вам нужно изменить:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    DataSource dataSource;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception{
        auth.jdbcAuthentication()
            .dataSource(dataSource)
    }
}

Но при поиске имен пользователей и паролей измените запрос базы данных Spring Security по умолчанию, чтобы вы могли создать схему базы данных, которая будет хорошей:

public static final String DEF_USERS_BY_USERNAME_QUERY =
"select username,password,enabled " +
"from users " +
"where username = ?";
public static final String DEF_AUTHORITIES_BY_USERNAME_QUERY =
"select username,authority " +
"from authorities " +
"where username = ?";
public static final String DEF_GROUP_AUTHORITIES_BY_USERNAME_QUERY =
"select g.id, g.group_name, ga.authority " +
"from groups g, group_members gm, group_authorities ga " +
"where gm.username = ? " +
"and g.id = ga.group_id " +
"and g.id = gm.group_id";

Но вы также можете использовать методы Spring для указания собственного запроса к базе данных:

auth
.jdbcAuthentication()
.dataSource(dataSource)
.usersByUsernameQuery(
"select username, password, enabled from Users " +
"where username=?")

Вы должны отправить свои данные в созданную вами службу, которая будет хранить пользователя и передавать в базу данных.

Я получил его, и он работает, но проблема в том, как я могу войти в систему? Я пытался отправить JSON в «/login» с именем пользователя и паролем, но он все равно перенаправлял меня на страницу входа (без ошибок/ничего)

Orzelke 25.03.2019 23:28

Если вы используете конфигурацию Spring Security Login, вам это не нужно, за исключением правильного ее хранения.

IvanM 25.03.2019 23:31

Я имею в виду, что хочу изменить форму на свою собственную, я знаю, как это сделать, но я не знаю, какой JSON я должен отправить в «/ логин» для аутентификации пользователя.

Orzelke 25.03.2019 23:36

В файле конфигурации Spring Security определите свою пользовательскую форму входа в систему, как указано здесь docs.spring.io/spring-security/site/docs/current/guides/html‌​5/…

IvanM 26.03.2019 09:30

Пожалуйста, не храните пароли в базе данных (или где-либо еще): храните только криптографические хэши.

Gwaptiva 27.07.2020 09:17
Ответ принят как подходящий

Попробуйте это, это может помочь вам... по крайней мере, понять, чего вам не хватает. Этот код не гарантирует 100% работоспособность, некоторые части намеренно упущены (обработка ошибок и их формат, загрузка пользователя, некоторые проверки, Session API).

Основная идея заключается в том, что вы должны зарегистрировать фильтр (реагировать на все защищенные запросы для процесса аутентификации) и провайдера, который позже сможет загрузить аутентифицированного пользователя и создать для вас контекст безопасности (например, вы знаете, что каждый запрос обрабатывается для каждого потока и этого пользователя можно получить с помощью SecurityContextHolder/ThreadLocal).

И вам нужно создать отдельный контроллер для обработки начального случая создания сеанса пользователя, также известного как вход/авторизация. Ответ этого API должен содержать GUID сеанса, чтобы использовать его в качестве значения заголовка позже: Authentication: Bearer <value>

некоторые спецификации: https://www.rfc-editor.org/rfc/rfc6750

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)//optional
@Import(RestSecurityConfig.TokenAuthenticationProvider.class)// one of the way to create spring bean
public class RestSecurityConfig extends WebSecurityConfigurerAdapter {
    private static final RequestMatcher PUBLIC_URLS = new OrRequestMatcher(
            new AntPathRequestMatcher("/actuator/*"),
            new AntPathRequestMatcher("/some_api_to_login", POST), // this must be public
    );
    private static final RequestMatcher PROTECTED_URLS = new NegatedRequestMatcher(PUBLIC_URLS);

    // better to move it out as a separate class
    public static class TokenAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
        @Override
        public boolean supports(Class<?> authentication) {
            return MyAuthenticationToken.class.isAssignableFrom(authentication);
        }

        @Override
        protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {

        }

        @Override
        protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
            return null; // service/dao.loadUser
        }
    }

    public static class TokenAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
        public TokenAuthenticationFilter(RequestMatcher requiresAuthenticationRequestMatcher) {
            super(requiresAuthenticationRequestMatcher);
        }

        @Override
        public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException {
            Authentication auth = new MyAuthenticationToken(request.getHeader("Authentication"));
            return getAuthenticationManager().authenticate(auth);
        }
    }

    @Autowired
    TokenAuthenticationProvider authenticationProvider;

    @Override
    protected void configure(final AuthenticationManagerBuilder auth) {
        auth.authenticationProvider(authenticationProvider);
    }

    @Override
    public void configure(final WebSecurity web) {
        web.ignoring().requestMatchers(PUBLIC_URLS);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // maybe some of the tuning you might not need
        http
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .exceptionHandling()
                .defaultAuthenticationEntryPointFor(new Http403ForbiddenEntryPoint(), PROTECTED_URLS).and()
                .authorizeRequests().anyRequest().authenticated().and()
                .cors().and()
                .anonymous().disable()
                .rememberMe().disable()
                .csrf().disable()
                .formLogin().disable()
                .httpBasic().disable()
                .logout().disable();

        // it's important
        http.addFilterBefore(tokenAuthenticationFilter(), AnonymousAuthenticationFilter.class);
    }

    @Bean
    AbstractAuthenticationProcessingFilter tokenAuthenticationFilter() throws Exception {
        final AbstractAuthenticationProcessingFilter filter = new TokenAuthenticationFilter(PROTECTED_URLS);
        filter.setAuthenticationManager(authenticationManager());
        filter.setAuthenticationSuccessHandler(successHandler());
        // maybe error handling to provide some custom response?
        return filter;
    }

    // it's critically important to register your filter properly in spring context
    /** Disable Spring boot automatic filter registration. */
    @Bean
    FilterRegistrationBean disableRegistrationForAuthenticationFilter(final TokenAuthenticationFilter filter) {
        final FilterRegistrationBean registration = new FilterRegistrationBean(filter);
        registration.setEnabled(false);
        return registration;
    }

    // this one also is critically important to avoid redirection
    @Bean
    SimpleUrlAuthenticationSuccessHandler successHandler() {
        final SimpleUrlAuthenticationSuccessHandler successHandler = new SimpleUrlAuthenticationSuccessHandler();
        successHandler.setRedirectStrategy(new NoRedirectStrategy());
        return successHandler;
    }

}

Другие вопросы по теме