不确定我在哪里配置错误的AuthorizationServer。代码成功从db中检索使用,然后出于某种原因我收到此错误:Access is denied (user is not anonymous); delegating to AccessDeniedHandler
。 (请参阅Auth服务器日志HERE)并不是用户登录以执行授权的全部原因。
我需要在哪里指定谁可以访问哪些内容?
授权服务器
@SpringBootApplication
@ComponentScan(basePackages = {"com.web.authserver"})
@EntityScan(basePackages = {"com.web.entity", "com.web.authserver"})
public class HLOAuth2AuthServerApplication {
public static void main(String[] args) {
SpringApplication.run(HLOAuth2AuthServerApplication.class, args);
}
@Configuration
@EnableAuthorizationServer
protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter {
@Autowired
DataSource dataSource;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.tokenStore(tokenStore())
.approvalStore(approvalStore())
.authorizationCodeServices(authorizationCodeServices());
}
@Bean
public JdbcClientDetailsService clientDetailsService() {
return new JdbcClientDetailsService(dataSource);
}
@Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
@Bean
public ApprovalStore approvalStore() {
return new JdbcApprovalStore(dataSource);
}
@Bean
public AuthorizationCodeServices authorizationCodeServices() {
return new JdbcAuthorizationCodeServices(dataSource);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(clientDetailsService());
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer
// will be applied to /oauth/token_key
.tokenKeyAccess("isAnonymous() || hasAuthority('ROLE_USER')")
// will be application to /oauth/check_token
.checkTokenAccess("hasAuthority('ROLE_TRUSTED_CLIENT') || hasAuthority('ROLE_USER') || hasAuthority('USER')")
.allowFormAuthenticationForClients();
}
}
@Configuration
protected static class AuthenticationManagerConfiguration extends GlobalAuthenticationConfigurerAdapter {
@Autowired
private CustomUserDetailsService customUserDetailsService;
@Override
public void init(AuthenticationManagerBuilder auth) throws Exception {
// @formatter:off
auth
.userDetailsService(customUserDetailsService)
.passwordEncoder(new BCryptPasswordEncoder());
// @formatter:on
}
}
}
资源服务器:
package com.hl.resources.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.security.oauth2.client.*;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.config.annotation.configurers.*;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
import javax.sql.DataSource;
@Configuration
@EnableResourceServer
public class OAuth2ResourceConfig extends ResourceServerConfigurerAdapter{
@Autowired
DataSource dataSource;
String RESOURCE_ID = "hl_data_resource";
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
TokenStore tokenStore = new JdbcTokenStore(dataSource);
resources
.resourceId(RESOURCE_ID)
.tokenStore(tokenStore);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.
anonymous()
.and().requestMatchers().antMatchers("/api/v1/users/user")
.and().authorizeRequests().antMatchers("/api/v1/users/user").access("#oauth2.hasScope('read')");
http
// For some reason we cant just "permitAll" OPTIONS requests which are needed for CORS support. Spring Security
// will respond with an HTTP 401 nonetheless.
// So we just put all other requests types under OAuth control and exclude OPTIONS.
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/**").access("#oauth2.hasScope('read')")
.antMatchers(HttpMethod.POST, "/**").access("#oauth2.hasScope('write')")
.antMatchers(HttpMethod.PATCH, "/**").access("#oauth2.hasScope('write')")
.antMatchers(HttpMethod.PUT, "/**").access("#oauth2.hasScope('write')")
.antMatchers(HttpMethod.DELETE, "/**").access("#oauth2.hasScope('write')")
.and()
// Add headers required for CORS requests.
.headers().addHeaderWriter((request, response) -> {
response.addHeader("Access-Control-Allow-Origin", "*");
if (request.getMethod().equals("OPTIONS")) {
response.setHeader("Access-Control-Allow-Methods", request.getHeader("Access-Control-Request-Method"));
response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers"));
}
});
http.authorizeRequests().antMatchers(HttpMethod.POST, "/v1/files/**").permitAll();
// @formatter:off
// http
// .requestMatchers().antMatchers("/bookmarks", "/bookmarks/**")
// .and()
// .authorizeRequests().anyRequest().access("#oauth2.hasScope('write')");
// @formatter:on
}
}
网络客户端应用
@SpringBootApplication
@EnableZuulProxy
@EnableOAuth2Sso
@EnableConfigurationProperties
public class HLOAuth2TestWebClientApplication {
public static void main(String[] args) {
SpringApplication.run(HLOAuth2TestWebClientApplication.class, args);
}
@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
protected static class SecurityConfiguration extends OAuth2SsoConfigurerAdapter {
@Autowired
OAuth2SsoProperties oAuth2SsoProperties;
@Override
public void match(RequestMatchers matchers) {
matchers.anyRequest();
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/index.html", "/home.html" ,"/login").permitAll()
.anyRequest().authenticated()
.and().csrf().csrfTokenRepository(csrfTokenRepository())
.and().addFilterAfter(csrfHeaderFilter(), CsrfFilter.class)
//.and().csrf().disable()
;
}
private Filter csrfHeaderFilter() {
return new OncePerRequestFilter() {
@Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class
.getName());
if (csrf != null) {
Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
String token = csrf.getToken();
if (cookie == null || token != null
&& !token.equals(cookie.getValue())) {
cookie = new Cookie("XSRF-TOKEN", token);
cookie.setPath("/");
response.addCookie(cookie);
}
}
filterChain.doFilter(request, response);
}
};
}
private CsrfTokenRepository csrfTokenRepository() {
HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
repository.setHeaderName("X-XSRF-TOKEN");
return repository;
}
}
}
Web客户端application.properties文件:
server.port=7070
server.context-path=
server.tomcat.basedir=target/tomcat
vaadin.servlet.url-mapping=/ui
security.basic.enabled=false
debug=true
logging.level.org.springframework.security=DEBUG
#spring.oauth2.sso.home.secure=false
#spring.oauth2.sso.home.path=/,/**/*.html
spring.oauth2.client.accessTokenUri = http://localhost:9090/a/oauth/token
spring.oauth2.client.userAuthorizationUri = http://localhost:9090/a/oauth/authorize
spring.oauth2.client.clientId = acme
spring.oauth2.client.id=testWebClient
spring.oauth2.client.clientSecret = acmesecret
spring.oauth2.client.scope[0]=openid
spring.oauth2.client.scope[1]=read
#spring.oauth2.client.grant-type=implicit
spring.oauth2.client.clientAuthenticationScheme = form
spring.oauth2.resource.userInfoUri = http://localhost:8080/api/v1/users/user
zuul.routes.resource.path = /resource/**
zuul.routes.resource.url = http://localhost:7070
zuul.routes.user.path = /user/**
zuul.routes.user.url = http://localhost:9090/a/v1/users/user
Web客户端服务器日志:
http://pastebin.com/raw.php?i=vi2wEzSA
授权服务器日志:
答案 0 :(得分:5)
来自日志:
2015-08-19 09:53:52.979 DEBUG 26748 --- [nio-9090-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor : Secure object: FilterInvocation: URL: /oauth/authorize?client_id=acme&redirect_uri=http://localhost:7070/login&response_type=code&scope=openid%20read&state=3hSgha; Attributes: [hasAnyRole('ROLE_USER')]
2015-08-19 09:53:52.979 DEBUG 26748 --- [nio-9090-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@5e1fbc04: Principal: com.healthlinx.entity.Authority@d191b368: Username: AlexanderBaranovsky@fake.com; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: [UserRole(id=1, roleName=USER)]; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: [UserRole(id=1, roleName=USER)]
2015-08-19 09:53:52.981 DEBUG 26748 --- [nio-9090-exec-1] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter@3591ec27, returned: -1
我们可以看到用户已经过身份验证(请参阅第2行),但是
/oauth/authorize
期望用户具有ROLE_USER
权限(参见第1行)。
如果我们看一下第二行,日志显示用户只有USER
权限,这就是WebExpressionVoter
返回-1的原因。
您可以将USER
授权机构更改为ROLE_USER
,看看是否能解决问题。