在尝试重新演示如何限制访问端点的书籍中的示例时,我遇到了意外行为 - 不允许具有许可角色的管理员访问:
$ curl -X POST \
> 'http://localhost:9090/oauth/token?grant_type=password&username=admin&password=password2' \
> -H 'authorization: Basic d2ViYXBwOndlYnNlY3JldA==' \
> -H 'cache-control: no-cache' \
> -d '"category":"test","document":"this is a test document"'
{"access_token":"6d149c21-6a48-41e8-885d-d6da70648b49","token_type":"bearer","expires_in":42860,"scope":"read,write,trust"}
$ curl -X GET \
> 'http://localhost:9090/resource?access_token=6d149c21-6a48-41e8-885d-d6da70648b49' \
> -H 'cache-control: no-cache' \
{"timestamp":1508464945487,"status":403,"error":"Forbidden","exception":"org.springframework.security.access.AccessDeniedException","message":"Access Denied","path":"/resource"}
以下是相关课程:
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManager();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication().withUser("user1").password("password1").roles("USER")
.and().withUser("admin").password("password2").roles("ADMIN");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().antMatchers("/**").permitAll().and()
// default protection for all resources (including /oauth/authorize)
.authorizeRequests()
.anyRequest().hasAnyRole("USER","ADMIN");
// ... more configuration, e.g. for form login
}
}
@Configuration
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authManager;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authManager);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory().withClient("webapp").secret("websecret").authorizedGrantTypes("password")
.scopes("read,write,trust");
}
}
@SpringBootApplication
@EnableAuthorizationServer
@EnableResourceServer
@RestController
@EnableGlobalMethodSecurity(prePostEnabled=true)
public class OauthServerApplication {
@RequestMapping("/resource")
@PreAuthorize("hasRole('ADMIN')")
public String resourceEndpoint() {
return "This resource is protected by the resource server.";
}
public static void main(String[] args) {
SpringApplication.run(OauthServerApplication.class, args);
}
}
我在这里缺少什么?
目标是只允许admin
用户访问资源端点,而拒绝访问常规用户user1
。
N.B。:下面的节实际上是我添加的内容:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().antMatchers("/**").permitAll().and()
// default protection for all resources (including /oauth/authorize)
.authorizeRequests()
.anyRequest().hasAnyRole("USER","ADMIN");
// ... more configuration, e.g. for form login
}
因为缺席在资源获取尝试期间(第二次请求)产生以下内容:
<html>
<head>
<title>Login Page</title>
</head>
<body onload='document.f.username.focus();'>
<h3>Login with Username and Password</h3>
<form name='f' action='/login' method='POST'>
<table>
<tr>
<td>User:</td>
<td>
<input type='text' name='username' value=''>
</td>
</tr>
<tr>
<td>Password:</td>
<td>
<input type='password' name='password'/>
</td>
</tr>
<tr>
<td colspan='2'>
<input name="submit" type="submit" value="Login"/>
</td>
</tr>
<input name="_csrf" type="hidden" value="1cbdad0b-181e-496c-aed0-eb633b29eab7" />
</table>
</form>
</body>
</html>
启用网络安全日志后,正如一些评论员所建议的那样:
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
.....
@Override
public void configure(WebSecurity web) throws Exception {
web.debug(true);
}
...}
这里是来自2个请求的部分结果服务器日志:
2017-10-20 07:17:27.836 WARN 12728 --- [ main] o.s.s.c.a.web.builders.WebSecurity :
********************************************************************
********** Security debugging is enabled. *************
********** This may include sensitive information. *************
********** Do not use in a production system! *************
********************************************************************
2017-10-20 07:17:29.116 INFO 12728 --- [ main] o.s.cloud.commons.util.InetUtils : Cannot determine local hostname
2017-10-20 07:17:29.180 INFO 12728 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Registering beans for JMX exposure on startup
2017-10-20 07:17:29.186 INFO 12728 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Bean with name 'configurationPropertiesRebinder' has been autodetected for JMX exposure
2017-10-20 07:17:29.187 INFO 12728 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Bean with name 'refreshEndpoint' has been autodetected for JMX exposure
2017-10-20 07:17:29.187 INFO 12728 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Bean with name 'restartEndpoint' has been autodetected for JMX exposure
2017-10-20 07:17:29.187 INFO 12728 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Bean with name 'environmentManager' has been autodetected for JMX exposure
2017-10-20 07:17:29.188 INFO 12728 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Bean with name 'refreshScope' has been autodetected for JMX exposure
2017-10-20 07:17:29.189 INFO 12728 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Located managed bean 'environmentManager': registering with JMX server as MBean [org.springframework.cloud.context.environment:name=environmentManager,type=EnvironmentManager]
2017-10-20 07:17:29.197 INFO 12728 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Located managed bean 'restartEndpoint': registering with JMX server as MBean [org.springframework.cloud.context.restart:name=restartEndpoint,type=RestartEndpoint]
2017-10-20 07:17:29.202 INFO 12728 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Located managed bean 'refreshScope': registering with JMX server as MBean [org.springframework.cloud.context.scope.refresh:name=refreshScope,type=RefreshScope]
2017-10-20 07:17:29.207 INFO 12728 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Located managed bean 'configurationPropertiesRebinder': registering with JMX server as MBean [org.springframework.cloud.context.properties:name=configurationPropertiesRebinder,context=6f7923a5,type=ConfigurationPropertiesRebinder]
2017-10-20 07:17:29.211 INFO 12728 --- [ main] o.s.j.e.a.AnnotationMBeanExporter : Located managed bean 'refreshEndpoint': registering with JMX server as MBean [org.springframework.cloud.endpoint:name=refreshEndpoint,type=RefreshEndpoint]
2017-10-20 07:17:29.338 INFO 12728 --- [ main] o.s.c.support.DefaultLifecycleProcessor : Starting beans in phase 0
2017-10-20 07:17:29.402 INFO 12728 --- [ main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 9090 (http)
2017-10-20 07:17:29.406 INFO 12728 --- [ main] c.e.spring.cloud.OauthServerApplication : Started OauthServerApplication in 6.879 seconds (JVM running for 7.264)
2017-10-20 07:18:20.584 INFO 12728 --- [nio-9090-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet 'dispatcherServlet'
2017-10-20 07:18:20.584 INFO 12728 --- [nio-9090-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started
2017-10-20 07:18:20.600 INFO 12728 --- [nio-9090-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 16 ms
2017-10-20 07:18:20.606 INFO 12728 --- [nio-9090-exec-1] Spring Security Debugger :
************************************************************
Request received for POST '/oauth/token?grant_type=password&username=user1&password=password1':
org.apache.catalina.connector.RequestFacade@5ace935e
servletPath:/oauth/token
pathInfo:null
headers:
host: localhost:9090
connection: keep-alive
content-length: 54
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36
cache-control: no-cache
origin: chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop
content-type: text/plain;charset=UTF-8
authorization: Basic d2ViYXBwOndlYnNlY3JldA==
postman-token: cd55952b-6c6f-6101-8f24-3942dee9b06a
accept: */*
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.8
cookie: JSESSIONID=F4526A8B6FD15FD35D3D84D25E2C3898
Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
LogoutFilter
BasicAuthenticationFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
]
************************************************************
2017-10-20 07:20:18.604 INFO 12728 --- [nio-9090-exec-4] Spring Security Debugger :
************************************************************
Request received for GET '/resource?access_token=5466dfff-f088-4097-8db9-4ed07f0b80a0':
org.apache.catalina.connector.RequestFacade@5ace935e
servletPath:/resource
pathInfo:null
headers:
host: localhost:9090
connection: keep-alive
cache-control: no-cache
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36
postman-token: 394b6610-1d18-eec7-338b-ab1de65cfeeb
accept: */*
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.8
cookie: JSESSIONID=F4526A8B6FD15FD35D3D84D25E2C3898
Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CsrfFilter
LogoutFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
]
************************************************************
2017-10-20 07:20:18.640 INFO 12728 --- [nio-9090-exec-4] Spring Security Debugger :
************************************************************
New HTTP session created: 1D899B6306F970E097CE746030A28E4A
Call stack:
at org.springframework.security.web.debug.Logger.info(Logger.java:44)
at org.springframework.security.web.debug.DebugRequestWrapper.getSession(DebugFilter.java:166)
at javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:240)
at javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:240)
at javax.servlet.http.HttpServletRequestWrapper.getSession(HttpServletRequestWrapper.java:240)
at org.springframework.security.web.savedrequest.HttpSessionRequestCache.saveRequest(HttpSessionRequestCache.java:59)
at org.springframework.security.web.access.ExceptionTranslationFilter.sendStartAuthentication(ExceptionTranslationFilter.java:201)
at org.springframework.security.web.access.ExceptionTranslationFilter.handleSpringSecurityException(ExceptionTranslationFilter.java:177)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:133)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:137)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:111)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:170)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:63)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:116)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.csrf.CsrfFilter.doFilterInternal(CsrfFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:64)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:56)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:331)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:214)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
at org.springframework.security.web.debug.DebugFilter.invokeWithWrappedRequest(DebugFilter.java:90)
at org.springframework.security.web.debug.DebugFilter.doFilter(DebugFilter.java:77)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:108)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:106)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1457)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
************************************************************
当我在资源端点顶部注释掉@PreAuthorize("hasRole('ADMIN')")
注释时,资源请求会正确显示&#34;此资源受资源服务器保护。&#34;还会触发放置在那里的断点。重新启用@PreAuthorize注释似乎会引入不正确的行为并跳过断点。我可以在周围的Spring基础设施中放置断点来深入研究@PreAuthorize("hasRole('ADMIN')")
注释的这种影响吗?
感谢。
答案 0 :(得分:0)
由于您使用的是 OAuth2 ,因此您需要使用 Bundle extras = getIntent().getExtras();
String transportItemChosen = extras.getString("SpinnerValue");
transportItemChosen = transportItemChosen.replace(".png", "");
transportItemChosen = transportItemChosen.replace("res/drawable/", "");
String uri = ("@drawable/" + transportItemChosen);
int id = getResources().getIdentifier(uri, null, getPackageName());
ImageView mImageView;
mImageView = (ImageView) findViewById(R.id.selectedimage);
mImageView.setImageResource(id);
而不是WebSecurityConfigurerAdapter
。例如:
ResourceServerConfigurerAdapter
现在您应该可以使用安全方法了。
Here是 OAuth2 的实施,其中 Spring Boot 包含自定义@Configuration
@EnableResourceServer
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().permitAll().and().cors().disable().csrf().disable().httpBasic().disable()
.exceptionHandling()
.authenticationEntryPoint(
(request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED))
.accessDeniedHandler(
(request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED));
}
}
服务和 JWT令牌。基本实现是一样的。
Here是授权服务器的UserDetails
Here是授权服务器的OAuth2Configuration