Mein Projekt besteht aus zwei verschiedenen Teilen, einem JSF-Admin-Panel und einem RESTfull-Service. Ich versuche, die Frühlingssicherheit so einzurichten, dass je nach der vom Benutzer navigierten URL unterschiedliche Authentifizierungsmethoden verwendet werden.
Die Anforderungen sind
Die separaten Konfigurationen funktionieren von selbst. Das Problem besteht darin, dass ich versuche, beide in einer Konfiguration zu kombinieren. In diesem Fall scheint der REST-Anbieter im Weg zu sein und jede Anforderung zu authentifizieren, selbst wenn die Anforderungen an die Administrator-URL gehen (dies) ist aus der Federsicherheitsbestellung dokumentiert).
Meine Beispielkonfigurationen sind wie folgt:
Für das Formular Login (JSF)
@Override
@Order(1)
protected void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/resources/**").permitAll()
.antMatchers("/templates/**").permitAll()
.antMatchers("/401.html").permitAll()
.antMatchers("/404.html").permitAll()
.antMatchers("/500.html").permitAll()
.antMatchers("/api/**").permitAll()
.antMatchers("/ui/admin.xhtml").hasAnyAuthority("admin", "ADMIN")
.antMatchers("/thymeleaf").hasAnyAuthority("admin", "ADMIN")
//.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/ui/index.xhtml")
.failureUrl("/login?error=1")
.permitAll()
.and()
.logout()
.permitAll()
.and()
.rememberMe()
.and().exceptionHandling().accessDeniedPage("/error/403");
OAuth2-Sicherheitskonfiguration (REST)
@EnableResourceServer
@Order(2)
public class RestSecurityConfig extends WebSecurityConfigurerAdapter {
@Inject
private UserRepository userRepository;
@Inject
private PasswordEncoder passwordEncoder;
@Bean
ApplicationListener<AbstractAuthorizationEvent> loggerBean() {
return new AuthenticationLoggerListener();
}
@Bean
AccessDeniedHandler accessDeniedHandler() {
return new AccessDeniedExceptionHandler();
}
@Bean
AuthenticationEntryPoint entryPointBean() {
return new UnauthorizedEntryPoint();
}
/*Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers(
"/resources/**"
, "/templates/**"
, "/login"
, "/logout"
, "/ui/**"
, "/401.html"
, "/404.html"
, "/500.html"
);
}*/
@Override
protected 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()
.antMatchers("/ui/**").permitAll()
.and()
.anonymous().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and().httpBasic()
.and()
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler()) // handle access denied in general (for example comming from @PreAuthorization
.authenticationEntryPoint(entryPointBean()) // handle authentication exceptions for unauthorized calls.
.defaultAuthenticationEntryPointFor(entryPointBean(), preferredMatcher)
.and()
.authorizeRequests()
.antMatchers("/api/**").fullyAuthenticated();
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(new UserDetailsService() {
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
User user = userRepository.findOneByUsername(s);
if (null == user) {
// leave that to be handled by log listener
throw new UsernameNotFoundException("The user with email " + s + " was not found");
}
return (UserDetails) user;
}
}).passwordEncoder(passwordEncoder);
}
@Configuration
@EnableAuthorizationServer
protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
return new JwtAccessTokenConverter();
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.tokenKeyAccess("isAnonymous() || hasAuthority('ROLE_TRUSTED_CLIENT')").checkTokenAccess("hasAuthority('ROLE_TRUSTED_CLIENT')");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager).accessTokenConverter(accessTokenConverter());
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("xxx")
.resourceIds(xxx)
.authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
.authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
.scopes("read", "write", "trust", "update")
.accessTokenValiditySeconds(xxx)
.refreshTokenValiditySeconds(xxx)
.secret("xxx")
}
}
}
Diese Konfigurationen existieren für verschiedene Klassen und die Reihenfolge wird manuell festgelegt.
Hat jemand irgendwelche Lösungen für dieses Problem?
Beste,
Ich habe versucht, Ihre Sicherheitskonfiguration anzupassen. Leider kann ich diese Konfiguration aufgrund fehlender Referenzanwendung nicht validieren.
Vielleicht kann es Ihnen helfen:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserRepository userRepository;
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(new UserDetailsService() {
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
User user = userRepository.findOneByUsername(s);
if (null == user) {
throw new UsernameNotFoundException("The user with email " + s + " was not found");
}
return (UserDetails) user;
}
}).passwordEncoder(passwordEncoder);
}
@Override
public void configure(WebSecurity webSecurity) throws Exception {
webSecurity
.ignoring()
.antMatchers("/resources/**"
, "/templates/**"
, "/login"
, "/logout"
, "/ui/**"
, "/401.html"
, "/404.html"
, "/500.html");
}
@Configuration
@EnableAuthorizationServer
public static class OAuth2Configuration extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
return new JwtAccessTokenConverter();
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.tokenKeyAccess("isAnonymous() || hasAuthority('ROLE_TRUSTED_CLIENT')").checkTokenAccess("hasAuthority('ROLE_TRUSTED_CLIENT')");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager).accessTokenConverter(accessTokenConverter());
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("xxx")
.resourceIds("xxx")
.authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
.authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
.scopes("read", "write", "trust", "update")
.accessTokenValiditySeconds(xxx)
.refreshTokenValiditySeconds(xxx)
.secret("xxx");
}
}
@Configuration
@Order(1)
public static class FormLoginWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http
.csrf().disable()
.authorizeRequests()
.antMatchers("/ui/admin.xhtml").hasAnyAuthority("admin", "ADMIN")
.antMatchers("/thymeleaf").hasAnyAuthority("admin", "ADMIN")
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/ui/index.xhtml")
.failureUrl("/login?error=1")
.permitAll()
.and()
.logout()
.permitAll()
.and()
.rememberMe()
.and().exceptionHandling().accessDeniedPage("/error/403");
}
}
@Order(2)
@Configuration
@EnableResourceServer
public static class CustomResourceServerConfigurerAdapter extends ResourceServerConfigurerAdapter {
@Bean
ApplicationListener<AbstractAuthorizationEvent> loggerBean() {
return new AuthenticationLoggerListener();
}
@Bean
AccessDeniedHandler accessDeniedHandler() {
return new AccessDeniedExceptionHandler();
}
@Bean
AuthenticationEntryPoint entryPointBean() {
return new UnauthorizedEntryPoint();
}
@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()
.accessDeniedHandler(accessDeniedHandler()) // handle access denied in general (for example comming from @PreAuthorization
.authenticationEntryPoint(entryPointBean()) // handle authentication exceptions for unauthorized calls.
.defaultAuthenticationEntryPointFor(entryPointBean(), preferredMatcher)
.and()
.authorizeRequests()
.antMatchers("/api/**").fullyAuthenticated();
}
}
}
Dieser Artikel stammt aus dem Internet. Bitte geben Sie beim Nachdruck die Quelle an.
Bei Verstößen wenden Sie sich bitte [email protected] Löschen.
Lass mich ein paar Worte sagen