Spring Boot 2 Как реализовать неявный поток кода - PullRequest
0 голосов
/ 12 января 2019

В настоящее время я нахожусь в процессе введения OAuth в мое приложение Spring, но мне не повезло, чтобы правильно его интегрировать Я использую Spring Boot 2 .

Мои требования:

  • Сервер авторизации и ресурсов - это одно и то же приложение , работающее на одном сервере
  • Неявный, код авторизации и полномочия владельца ресурса необходимо поддерживать потоки
  • API, который я хочу защитить жизни в "/ api / v1 /"

Ни один из потоков не работает правильно. То, чего я достиг до сих пор, основано на учебном пособии https://www.devglan.com/spring-security/spring-oauth2-role-based-authorization и ответе: https://stackoverflow.com/a/52386009/4454752

Так что мой Сервер авторизации выглядит так:

@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

  private final AuthenticationManager authenticationManager;

  @Autowired
  public AuthorizationServerConfig(AuthenticationManager authenticationManager) {
    this.authenticationManager = authenticationManager;
  }

  @Bean
  public JwtAccessTokenConverter accessTokenConverter() {
    JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
    converter.setSigningKey("as466gf");
    return converter;
  }

  @Bean
  public TokenStore tokenStore() {
    return new JwtTokenStore(accessTokenConverter());
  }


  @Override
  public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    clients
      .inMemory()
      .withClient("my-client-id")
      .authorizedGrantTypes("authorization_code", "implicit", "refresh_token", "password")
      .authorities("ADMIN")
      .scopes("all")
      .resourceIds("product_api")
      .secret("$2a$10$jfAHmk4szDU/t1qLGlFTLukuBZL0ZHZGUJQICePjjyq6IrLOS934.")
      .redirectUris("https://example.com")
      .accessTokenValiditySeconds(7200)
      .refreshTokenValiditySeconds(7200);
  }

  @Override
  public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
    oauthServer
      .tokenKeyAccess("permitAll()")
      .checkTokenAccess("permitAll()");
  }

  @Override
  public void configure(AuthorizationServerEndpointsConfigurer endpoints) {

    endpoints
      .authenticationManager(authenticationManager)
      .accessTokenConverter(accessTokenConverter());
  }

}

Тогда ResourceServer

   @Configuration
@EnableResourceServer
@Order(2)
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {


  @Override
  public void configure(ResourceServerSecurityConfigurer resources) {
    resources.resourceId("product_api");
  }

  @Override
  public void configure(HttpSecurity http) throws Exception {
    http
      .requestMatchers()
      .antMatchers("/**")
      .and().authorizeRequests()
      .antMatchers("/**").permitAll()
      .and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
  }


}

И, наконец, WebSecurityConfig

@Configuration
@Order(1)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

  @Resource(name = "userDetailService")
  private UserDetailService userDetailsService;

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

  @Override
  @Bean
  public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
  }

  @Autowired
  public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService).passwordEncoder(encoder());
  }

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

    http.authorizeRequests()
      .antMatchers("/api/v1/**")
      .hasAnyRole("ADMIN", "USER").and()
      .httpBasic().and().formLogin().and().authorizeRequests().anyRequest().authenticated();
  }

  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth
      .userDetailsService(userDetailsService)
      .passwordEncoder(encoder());
  }
}

Мой UserDetails и полное управление пользователями уже настроены, поэтому здесь не нужно что-то менять.

Теперь к случаям использования.

Если доступ "/ oauth / token":

curl --request POST \
  --url http://localhost:8080/oauth/token \
  --header 'authorization: Basic bXktY2xpZW50Om15LXNlY3JldA==' \
  --header 'content-type: application/x-www-form-urlencoded' \
  --data 'grant_type=password&username=admin&password=test'

Так что с my-client: my-secret я получаю ответ с токеном доступа и токеном обновления. Но если я хочу использовать токен доступа в моем API, я получаю Access denied. Если я проверяю токен с /oauth/check_token, он говорит, что токен действителен.

Та же проблема, если я использую "/ oauth / authorize" (неявный поток). Я знаю, что мне нужна страница входа с весны, чтобы она работала, поэтому я добавил formLogin() в WebSecurityConfig. Но если я запрашиваю http://localhost:8080/oauth/authorize?response_type=token&client_id=my-client&redirect_uri=https://example.com, меня перенаправляют на /login, я вхожу в систему, затем получаю токен доступа из URL-адреса перенаправления, но снова, если я использую этот токен, я получаю ошибку 401.

Конечная точка, к которой я хочу получить доступ, обрабатывается следующим контроллером:

@RestController
@RequestMapping(value = "/api/v1/user")
@CrossOrigin(origins = "*")
public class UserController {

  private static final Logger LOGGER = LogManager.getLogger(UserController.class);
  public static final String ROLE_USER = "ROLE_USER";



  private final AuthenticationFacade authenticationFacade;
  private final UserService userService;

  @Autowired
  public UserController(AuthenticationFacade authenticationFacade,
    UserService userService) {
    this.authenticationFacade = authenticationFacade;
    this.userService = userService;
  }

  @RequestMapping(value = "/me", method = RequestMethod.GET)
  public Optional<User> getCurrentUser() {
    LOGGER.info("Requesting /api/v1/user/me");
    return userService.findByUsername((String) authenticationFacade.getAuthentication().getPrincipal());
  }
}

Я почти уверен, что что-то с настройкой безопасности испортилось, но я понятия не имею, что это может быть. Я просмотрел множество руководств в Интернете, но не нашел ни одного, в котором объясняется весь код авторизации, объединенный. Я думаю, что это может быть небольшая ошибка с аутентификацией URL, но я понятия не имею, что это может быть.

Я был бы очень рад, если бы кто-то знал ответ на этот вопрос.

1 Ответ

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

Переместите реализацию configure () из WebSecurityConfig в метод configure () сервера ресурсов, как показано ниже

http.authorizeRequests()
      .antMatchers("/api/v1/**")
      .hasAnyRole("ADMIN", "USER")

Остальные конфигурации в методе configure () не требуются

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...