Как использовать RESTful с базовой аутентификацией в Spring Boot - PullRequest
0 голосов
/ 03 января 2019

Helllo, я использую RESTful с базовой аутентификацией, и этот код является частью RestController:

@GetMapping("/jpa/users/{username}/goals")
public List<Goal> getAllGoals(@PathVariable String username) {
    userId = getUserIdFromUsername(username);
    return goalJpaRepository.findByUserId(userId); 
}

public Long getUserIdFromUsername(String username) {
    User user = userJpaRepository.findByUsername(username);
    userId = user.getId(); 
    return userId;
}

И у меня есть проблема, например, я использую Почтальон, чтобы получить цели для конкретного пользователя, например:

http://localhost:8080/jpa/users/john/goals с запросом GET

Затем я использую базовую аутентификацию для имени пользователя john и пароль для этого имени пользователя и получаю цели для john.

После этого, если я сделаю запрос GET по этой ссылке http://localhost:8080/jpa/users/tom/goals Я получу цели для Тома, но в данный момент я вошел в систему с Джоном, поэтому Джон может видеть свои цели, а также он можно увидеть цели Тома.

Вопрос в том, как мне получить доступ к имени пользователя для входа в RestController, потому что я хочу сделать что-то вроде этого:

if (loginUsername == username) {
    return goalJpaRepository.findByUserId(userId);
} 

return "Access denied!";

Итак, я хочу знать, возможно ли получить доступ к имени пользователя для входа из заголовка HTTP?

Спасибо!


ОБНОВЛЕНИЕ - Да, инфраструктура - Spring Boot, также я использую Spring Security с аутентификацией Dao, потому что я хочу получить пользователя из базы данных MySQL. Во всяком случае, я не эксперт в Spring Security.

Теперь я понимаю, как использовать Principal в моих методах контроллера, но я не знаю, как использовать Spring Security для этого конкретного случая. Как мне это реализовать? Например, пользователь john должен видеть и изменять только свои цели.

Конфигурация безопасности Spring:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

import com.dgs.restful.webservices.goaltrackerservice.user.MyUserDetailsService;

@Configuration
@EnableWebSecurity
public class SpringSecurityConfigurationBasicAuth extends WebSecurityConfigurerAdapter {

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Autowired
    private MyUserDetailsService userDetailsService;

    @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider authProvider
          = new DaoAuthenticationProvider();
        authProvider.setUserDetailsService(userDetailsService);
        authProvider.setPasswordEncoder(bCryptPasswordEncoder());
        return authProvider;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http
            .csrf().disable()
            .authorizeRequests()
            .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
            .antMatchers("/allusers").permitAll()
                .anyRequest().authenticated()
                .and()
            // .formLogin().and()
            .httpBasic();
        }

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

Ответы [ 5 ]

0 голосов
/ 04 января 2019

Чтобы ответить на ваш новый вопрос по «Аутентификация Dao» , ответом будет предоставить пользовательский UserDetailsService.

Из конфигурации, которую вы прикрепили к вашему вопросу, похоже, что у вас уже есть MyUserDetailsService.

Существует множество статей, в которых объясняется, как использовать пользовательские DetailsService. Это, кажется, соответствует вашим требованиям: https://www.baeldung.com/spring-security-authentication-with-a-database

Редактировать : Как быть уверенным, что только Джон может видеть предметы Джона.

По сути, единственное, что вы можете сделать, чтобы убедиться, что только Джон может видеть свои цели, это ограничить цели только теми, которые принадлежат Джону. Но есть много способов сделать это.

  1. Как вы предлагаете в своем первоначальном вопросе, вы можете просто выбрать цели для конкретного пользователя. Преимущество Spring-Security заключается в том, что он может вводить Principal, но также и другой тип объекта аутентификации.

  2. Вы также можете сделать это более неявным фильтром на стороне DAO / Repository, используя SecurityContextHolder. Этот подход хорош и выглядит лучше, когда ваша система более ориентирована на пользователя или похожа на мультитенантную систему.

  3. Использование некоторых специфических @Annotations или Aspect также будет решением, но, возможно, менее очевидным в этом случае.

0 голосов
/ 03 января 2019

Эту проблему также можно решить с помощью @PreAuthorize, аннотации, предлагаемой Spring Security Framework, в которой используется язык выражений Spring.

@PreAuthorize("principal.name == #username")
@GetMapping("/jpa/users/{username}/goals")
public List<Goal> getAllGoals(@PathVariable String username) {
    return goalJpaRepository.findByUserId(userId); 
}

За кулисами Spring будет использовать уже упомянутые SecurityContextHolder чтобы получить аутентифицированного в данный момент участника.Если выражение принимает значение false, будет возвращен код ответа 403.

Обратите внимание, что необходимо включить глобальную защиту метода:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {

}
0 голосов
/ 03 января 2019

Ответ уже дан перед ответами.Я просто хочу сделать дополнение, взгляните на эту статью.Вы можете легко реализовать Spring Security с токеном JSON:

https://auth0.com/blog/implementing-jwt-authentication-on-spring-boot/

0 голосов
/ 03 января 2019

Предполагая, что вы используете Spring в качестве платформы Java, вы должны использовать Spring Security для настройки базовой аутентификации.Многие учебные материалы, доступные в Интернете (https://www.baeldung.com/spring-security-basic-authentication,

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

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

Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String loginUsername = authentication.getName();

В качестве альтернативы, как упомянуто @ gervais.b Spring может ввести Principal (или Authentication) в методах вашего контроллера.

Как сказал @Glains Еще более удачной альтернативой является использование аннотаций @PreAuthorize и @PostAuthorize, которые позволяют вам определять простые правила на основе Spring Expression Language.

0 голосов
/ 03 января 2019

Обратите внимание, что в настоящее время вы не принимаете никаких мер безопасности.

Как говорит @Matt "Это зависит от того, какую платформу вы используете" .Но я думаю, что вы используете весну.Затем вы должны взглянуть на документацию по модулю spring-securuty.

По сути, вы можете добавить аутентифицированного пользователя в параметр вашего метода:

   @GetMapping("/jpa/users/{username}/goals")
   public List<Goal> getAllGoals(@PathVariable String username, Principal principal) {
     if ( username.equals(principal.getName()) ) {
       userId = getUserIdFromUsername(username);
       return goalJpaRepository.findByUserId(userId); 
     } else {
       throw new SomeExceptionThatWillBeMapped();
     }
   } 

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

...