Spring Boot2 Oauth2 Implicit Flow - http: // localhost: 8080 / oauth / authorize получение отказа в доступе

Я создал приложение Spring Boot 2, интегрированное SpringFox Swagger 2.8.0 с неявным грантом Oauth2 для аутентификации и авторизации.

Код работает нормально, но когда я нажимаю кнопку «Авторизовать», он перенаправляется на

HTTP: // локальный: 8080 / OAuth / авторизированным response_type = маркер & client_id = тест-приложение-клиент-идентификатор & redirect_uri = HTTP% 3A% 2F% 2Flocalhost% 3A8080 % 2Fwebjars% 2Fspringfox-swagger-ui% 2Foauth2-redirect.html & scope = read & state = U3VuIE9jdCAxNCAyMDE4IDIwOjQyOjUwIEdNVCswNTMwIChJbmRpYSBTdGFuZ

но показывает "Доступ запрещен", как показано ниже.

Мой полный проект доступен в GitHub.

MainApplication.java

@EnableSwagger2
@SpringBootApplication
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@RestController
public class MainApplication /*extends WebMvcConfigurerAdapter*/
{

    public static void main(String[] args)
    {
        SpringApplication.run(MainApplication.class, args);
    }

    @RequestMapping("/user")
    public Principal user(Principal user) {
        return user;
    }

    @Bean
    SecurityConfiguration security() {
      return SecurityConfigurationBuilder.builder()//<19>
          .clientId("test-app-client-id")
          .build();
    }

    @Bean
    SecurityScheme oauth() {
          List<GrantType> grantTypes = new ArrayList<>();
          ImplicitGrant implicitGrant = new ImplicitGrant(new LoginEndpoint("http://localhost:8080/oauth/authorize"),"access_code");
          grantTypes.add(implicitGrant);
          List<AuthorizationScope> scopes = new ArrayList<>();
          scopes.add(new AuthorizationScope("read","Read access on the API"));
        return new OAuthBuilder()
                .name("SECURITY_SCHEME_OAUTH2")
                .grantTypes(grantTypes)
                .scopes(scopes)
                .build();
    }

    @Bean
    public Docket docket()
    {
        return new Docket(DocumentationType.SWAGGER_2)
            .select()
            .apis(RequestHandlerSelectors.basePackage(getClass().getPackage().getName()))
            .paths(PathSelectors.any())
            .build()
            .securitySchemes(Collections.singletonList(oauth()))
            .apiInfo(generateApiInfo());
    }


    private ApiInfo generateApiInfo()
    {
        return new ApiInfo("Sample Service", "This service is to check Sample Service.", "Version 1.0",
            "Sample Service", "[email protected]", "Apache 2.0", "http://www.apache.org/licenses/LICENSE-2.0");
    }
}

введите описание изображения здесь

Обновление 1

Я добавил параметры безопасности и пароль, предложенные @AlexanderPetrov. Все работает нормально, когда я добавляю @EnableResourceServer, мой экран входа в систему показывает Для доступа к этому ресурсу требуется полная аутентификация, как показано ниже.

введите описание изображения здесь

Может ли кто-нибудь помочь мне в этом


person Alex Man    schedule 14.10.2018    source источник


Ответы (2)


Вам необходимо внести следующие изменения в свой код

  1. Конфигурация входа в форму необходима для неявного потока.
  2. Также, если мы используем неявный токен потока, он будет сгенерирован через URL-адрес авторизации вместо URL-адреса токена. Поэтому вам нужно изменить "/ oauth / token" на "oauth / authorize". сконфигурируйте метод ниже

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/oauth/authorize").authenticated()
        .and()
        .authorizeRequests().anyRequest().permitAll()
        .and()
        .formLogin().permitAll()
        .and()
        .csrf().disable();
    }
    
  3. Добавьте кодировщик паролей в класс SecurityConfig и вызовите его для кодирования пароля пользователя в методе globalUserDetails. Кодировщик необходим, потому что вы используете пароли в памяти. Итак, без кодировщика паролей приложение выходит из строя с ошибкой:

    Encoded password does not look like BCrypt
    

Фрагмент кода ниже

@Autowired
public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
    PasswordEncoder passwordEncoder = passwordEncoder();
    auth.inMemoryAuthentication().passwordEncoder(passwordEncoder()).
            withUser("bill").password(passwordEncoder.encode("abc123")).roles("ADMIN").and()
            .withUser("$2a$10$TT7USzDvMxMZvf0HUVh9p.er1GGnjNQzlcGivj8CivnaZf9edaz6C")
            .password("$2a$10$TT7USzDvMxMZvf0HUVh9p.er1GGnjNQzlcGivj8CivnaZf9edaz6C").roles("USER");
}

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

Надеюсь, это поможет. Я создал ветку для вашего проекта, но не смог ее запустить из-за 403. Итак, весь необходимый код здесь, в моем ответе.

person Alexander Petrov    schedule 18.10.2018
comment
Извините, я просто вставил неверную конфигурацию для HttpSecurity. Я отредактировал свой ответ. Пожалуйста, проверьте это еще раз. - person Alexander Petrov; 18.10.2018
comment
не могли бы вы объяснить, что вы имели в виду, чтобы скрыть отображение client_id. Если я вас правильно понимаю, вы хотите скрыть значение client_id? - person Alexander Petrov; 18.10.2018
comment
Я обновил это, но когда я добавляю @EnableResourceServer, я получаю 401 для моего входа в систему. Вы можете проверить мое обновление - person Alex Man; 19.10.2018
comment
любая идея по этому поводу - person Alex Man; 06.11.2018

Когда вы включаете сервер ресурсов, вам необходимо настроить URL-адрес check_token, чтобы он мог подключиться к серверу авторизации OAuth2 и проверить данный access_token.

Вы можете сделать что-то вроде:

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

    @Value("${oauth.url.internal}")    // e.g. http://localhost:8082/oauth
    private String oauthUrl;

    @Value("${oauth.client}")
    private String oauthClient;

    @Value("${oauth.secret}")
    private String oauthSecret;

    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        return new OAuth2MethodSecurityExpressionHandler();
    }

    @Primary
    @Bean
    public RemoteTokenServices tokenService() {
        RemoteTokenServices tokenService = new RemoteTokenServices();
        tokenService.setCheckTokenEndpointUrl(oauthUrl + "/check_token");
        tokenService.setClientId(oauthClient);
        tokenService.setClientSecret(oauthSecret);
        return tokenService;
    }
}

Помимо этого, вы можете игнорировать конечные точки, специфичные для Swagger:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/v2/api-docs", "/configuration/ui", "/swagger-resources", "/configuration/security", "/swagger-ui.html", "/webjars/**");
    }
}

На всякий случай это класс, который я реализовал для авторизации Swagger с OAuth2:

@EnableSwagger2
@Configuration
public class SwaggerConfig implements WebMvcConfigurer {

    private static final String BASE_PACKAGE = "com.somepackage.api";

    @Value("${oauth.url}")    // Make sure this is an external URL, i.e. accessible from Swagger UI
    private String oauthUrl;

    @Value("${swagger.scopes}")
    private String swaggerScopes;

    @Value("${swagger.urls}")
    private String swaggerUrls;    // Your v2/api-docs URL accessible from the UI

    @Bean
    public Docket api(){
        return new Docket(DocumentationType.SWAGGER_2)
            .select()
            .apis(RequestHandlerSelectors.basePackage(BASE_PACKAGE))
            .apis(RequestHandlerSelectors.any())
            .paths(PathSelectors.any())
            .build()
            .securitySchemes(Collections.singletonList(securitySchema()))
            .securityContexts(Collections.singletonList(securityContext()));
    }

    private OAuth securitySchema() {
        List<AuthorizationScope> authorizationScopeList = new ArrayList<>();
        authorizationScopeList.add(new AuthorizationScope(swaggerScopes, ""));

        List<GrantType> grantTypes = new ArrayList<>();
        GrantType creGrant = new ResourceOwnerPasswordCredentialsGrant(oauthUrl + "/token");
        grantTypes.add(creGrant);

        return new OAuth("oauth2schema", authorizationScopeList, grantTypes);
    }

    private SecurityContext securityContext() {
        return SecurityContext.builder().securityReferences(defaultAuth()).forPaths(PathSelectors.ant(swaggerUrls)).build();
    }

    private List<SecurityReference> defaultAuth() {
        final AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = new AuthorizationScope(swaggerScopes, "");
        return Collections.singletonList(new SecurityReference("oauth2schema", authorizationScopes));
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");

        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }
}

Версии:

  • springSecurityVersion = '2.0.5.RELEASE'
  • swaggerVersion = '2.8.0'
  • springBootVersion = '2.0.5.RELEASE'
person Fabio Manzano    schedule 08.11.2018