Аутентификация Spring Security OAuth2 и вход в форму в одном приложении

Можно ли совместить авторизацию и аутентификацию по логину basic и по oauth2 в одном приложении?

Мой проект основан на проекте jhipster с простым входом в сеанс весенней безопасности, теперь мне нужно добавить безопасность oauth2 для мобильного приложения, и похоже, что это невозможно.

Теперь у меня есть ситуация, когда работает один из них, oauth2 в порядке, если WebSecurityConfigurerAdapter имеет больший номер заказа, чем ResourceServerConfiguration. Это означает, что фильтр безопасности oauth стоит первым. Я много читал в stackoverflow и пробовал много решений, таких как: конфигурация для меня это не работает.
Теперь я знаю, что это связано с некоторым конфликтом фильтров безопасности, но я не знаю, как это исправить.

если у кого то была похожая проблема и ему удалось это сделать, или знает как обойти или сделать лучше буду благодарен за информацию. Заранее спасибо за вашу помощь :)

@Configuration
@EnableWebSecurity
public class SecurityOauth2Configuration extends WebSecurityConfigurerAdapter {

  @Inject
  private UserDetailsService userDetailsService;

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

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

@Override
public void configure(WebSecurity web) throws Exception {
    web.ignoring()
        .antMatchers("/scripts/**/*.{js,html}")
        .antMatchers("/bower_components/**")
        .antMatchers("/i18n/**")
        .antMatchers("/assets/**")
        .antMatchers("/swagger-ui/index.html")
        .antMatchers("/api/register")
        .antMatchers("/api/activate")
        .antMatchers("/api/account/reset_password/init")
        .antMatchers("/api/account/reset_password/finish")
        .antMatchers("/test/**");
}


@Configuration
@EnableAuthorizationServer
public static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

    private static final String OAUTH_SECURITY = "jhipster.security.authentication.oauth.";
    private static final String CLIENTID = "clientid";
    private static final String SECRET = "secret";
    private static final String TOKEN_VALIDATION_TIME = "tokenValidityInSeconds";

    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer.tokenKeyAccess("isAnonymous() || hasAuthority('"+AuthoritiesConstants.USER+"')").checkTokenAccess("hasAuthority('"+AuthoritiesConstants.USER+"')");
    }
    @Inject
    private Environment env;
    @Inject
    private DataSource dataSource;

    @Bean
    public TokenStore tokenStore() {
        return new JdbcTokenStore(dataSource);
    }
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
            .authenticationManager(authenticationManager)
            .tokenStore(tokenStore())
        ;
    }




    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients
            .inMemory()
            .withClient(env.getProperty(OAUTH_SECURITY + CLIENTID))
            .scopes("read", "write")
            .authorities(AuthoritiesConstants.ADMIN, AuthoritiesConstants.USER)
            .authorizedGrantTypes("password", "refresh_token")
            .secret(env.getProperty(OAUTH_SECURITY + SECRET))
            .accessTokenValiditySeconds(env.getProperty(OAUTH_SECURITY + TOKEN_VALIDATION_TIME, Integer.class, 18000));

    }
}


@Configuration
@Order(1)
public static class SecurityWebConfiguration extends WebSecurityConfigurerAdapter {
    @Inject
    private Environment env;

    @Inject
    private AjaxAuthenticationSuccessHandler ajaxAuthenticationSuccessHandler;

    @Inject
    private AjaxAuthenticationFailureHandler ajaxAuthenticationFailureHandler;

    @Inject
    private AjaxLogoutOauthSuccessHandler ajaxLogoutSuccessHandler;

    @Inject
    private RememberMeServices rememberMeServices;


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


        http
                .csrf().disable().authorizeRequests()
            .and()
                .formLogin()
                .loginProcessingUrl("/api/authentication")
                .successHandler(ajaxAuthenticationSuccessHandler)
                .failureHandler(ajaxAuthenticationFailureHandler)
                .usernameParameter("j_username")
                .passwordParameter("j_password")
                .permitAll()
            .and()
                .rememberMe()
            .rememberMeServices(rememberMeServices)
                .key(env.getProperty("jhipster.security.rememberme.key"))
            .and()
                .logout()
            .logoutUrl("/api/logout")
            .logoutSuccessHandler(ajaxLogoutSuccessHandler)
            .deleteCookies("JSESSIONID")
                .permitAll()
            .and()
                .exceptionHandling()
        ;



    }

}


@Order(2)
@Configuration
@EnableResourceServer
public static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
    @Inject
    private Http401UnauthorizedEntryPoint authenticationEntryPoint;

    @Inject
    private AjaxLogoutOauthSuccessHandler ajaxLogoutSuccessHandler;

    @Override
    public void configure(HttpSecurity http) throws Exception {
        ContentNegotiationStrategy contentNegotiationStrategy = http.getSharedObject(ContentNegotiationStrategy.class);
        if (contentNegotiationStrategy == null) {
            contentNegotiationStrategy = new HeaderContentNegotiationStrategy();
        }
        MediaTypeRequestMatcher preferredMatcher = new MediaTypeRequestMatcher(contentNegotiationStrategy,
            MediaType.APPLICATION_FORM_URLENCODED,
            MediaType.APPLICATION_JSON,
            MediaType.MULTIPART_FORM_DATA);


        http
            .authorizeRequests()
            .and()
                .anonymous()
            .disable()
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
                .httpBasic()
            .and()
                .exceptionHandling()
                .authenticationEntryPoint(authenticationEntryPoint)
                .defaultAuthenticationEntryPointFor(authenticationEntryPoint, preferredMatcher)
            .and()
                .authorizeRequests()
                .antMatchers("/api/**").fullyAuthenticated();


    }
}

}

Для этого настройки сеанса WebSecurityConfigurerAdapter работают корректно. Для OAuth после правильной авторизации я получаю действительный токен доступа, но для запроса с этим токеном из сеанса я получаю этот результат:

  public static String getCurrentLogin() {
    SecurityContext securityContext = SecurityContextHolder.getContext();
    Authentication authentication = securityContext.getAuthentication();


    UserDetails springSecurityUser = null;
    String userName = null;
    if(authentication != null) {
        if (authentication.getPrincipal() instanceof UserDetails) {
            springSecurityUser = (UserDetails) authentication.getPrincipal();
            userName = springSecurityUser.getUsername();
        } else if (authentication.getPrincipal() instanceof String) {
            userName = (String) authentication.getPrincipal();
        }
    }
    System.out.println(userName);                          // show anonymousUser
    System.out.println(authentication.isAuthenticated());  //show true
    System.out.println(authentication.getAuthorities());   //show [ROLE_ANONYMOUS]
    System.out.println(userName);                          //show anonymousUser

    return userName;
}

функция пишет в консоли: анонимный пользователь true [ROLE_ANONYMOUS] анонимный пользователь

и должно быть user1 true [ROLE_USER] user1


person Wojciech    schedule 25.10.2015    source источник
comment
Не могли бы вы опубликовать простое, но полностью работающее демонстрационное приложение, демонстрирующее вашу проблему, на Github или где-нибудь еще? Спасибо   -  person ksokol    schedule 25.10.2015


Ответы (1)


URL-адреса приложений git: https://github.com/rynkowsw/oauth2 это приложение oauth2 https://github.com/rynkowsw/web-and-oauth2-security это веб и приложение безопасности oauth2

Это приложение адаптировано с сайта jhipster.github.io.

для запуска приложения вам нужно иметь postgres db на локальном хосте, например, в файле ресурсов db:

    driver-class-name: org.postgresql.ds.PGSimpleDataSource
    url: jdbc:postgresql://localhost:5432/gymapp
    name: gymapp
    serverName: localhost:5432
    username: postgres
    password: jaja

Самый быстрый способ протестировать приложение:

 http://localhost:8080/oauth/token
 headers:  Authorization: Basic amhpcHN0ZXJhcHA6bXlTZWNyZXRPQXV0aFNlY3JldA==

эта строка после базового является комбинацией по умолчанию jhispter oauth secret и clientid base64 encrypt result

потом

  http://localhost:8080/api/account
  headers:  Authorization: bearer [token from response in first request]

Для этой же базы данных результат для oauth: для приложения oauth2

{
 login: "user"
 password: null
 firstName: "User"
 lastName: "User"
 email: "user@localhost"
 activated: true
 langKey: "en"
 authorities: [1]
 0:  "ROLE_USER"
 -
}

для безопасности веб + oauth2:

 {
  login: "anonymousUser"
  password: null
  firstName: "Anonymous"
  lastName: "User"
  email: "anonymous@localhost"
  activated: true
  langKey: "en"
  authorities: [0]
  }
person Wojciech    schedule 26.10.2015
comment
вы нашли на него ответ? - person Ibrahim; 18.08.2017