login basic と oauth2 による承認と認証を 1 つのアプリケーションで組み合わせることができますか?
私のプロジェクトは、単純な春のセキュリティ セッション ログインを備えた jhipster プロジェクトに基づいています。モバイル アプリに oauth2 セキュリティを追加する必要がありますが、それは不可能のようです。
WebSecurityConfigurerAdapter が ResourceServerConfiguration よりも大きい注文番号を持っていれば、そのうちの 1 つを動作させることができます。これは、oauth セキュリティ フィルターが最初の場合の平均です。私はstackoverflowで多くのことを読んで、次のような多くのソリューションを試しました
.Springセキュリティoauth2とフォームログイン構成は機能しません。
セキュリティフィルターの競合に関連していることはわかっていますが、修正方法はわかりません。
誰かが同様の問題を抱えていて、彼がそれをなんとかやり遂げた場合、または回避する方法や改善する方法を知っている場合、私はその情報に感謝します. よろしくお願いします:)
@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;
}
関数はコンソールに書き込みます: anonymousUser true [ROLE_ANONYMOUS] anonymousUser
user1 true [ROLE_USER] user1 である必要があります