我使用教程http://projects.spring.io/spring-security-oauth/docs/tutorial.html中的sparklr2和tonr2的示例来获得OAuth 2提供程序。 sparklr2是一个已实现OAuth 2流的服务器。 sparklr2有资源 - 照相。 用户将通过tonr2访问sparklr2的photogalery。
如果我调用未修改的sparklr2(服务器)和tonr2(客户端),我有以下流程:
我使用tonr2的用户登录tonr2,然后点击“查看我的Sparklr照片”。 然后我用sparklr2的用户登录sparklr2。 然后将发生授权站点,我允许scope.read和scope.write。 然后我可以看到照片。
现在我将在其他客户端应用程序中使用授权代码流作为tonr2。以下步骤是成功的: 使用sparklr2的用户登录。 (具有/ login的uri将作为GET发送)
登录后显示授权站点(使用给定的client_id进行/ oauh / authorize,并给出redirect_uri和response_type = code& scope = read + write)
我有麻烦,如果我使用redirect_url给出的参数的授权码 - 如果我尝试通过POST请求访问令牌curl:
“curl -X POST http://geodez.com/oauth/token -F client_id = tonr -F client_secret = mysecret -F code = 1IfhzU”
将返回以下错误: “{”error“:”unauthorized“,”error_description“:”访问此资源需要完全身份验证“}”
我通过sparklr2查看loggin并找到以下内容:
“POST / oauth / token”与“GET”不匹配
我不知道,如何允许。我试图修改配置类,但它失败了:
我的修改配置类:
OAuth 2,授权代码流程:访问令牌请求:POST / oauth / token'与'GET / **不匹配 POST / oauth / token'与'GET / **
不匹配==================
org.myt.springframework.config.MethodSecurityConfig
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.myt.springframework.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
import org.springframework.security.oauth2.provider.expression.OAuth2MethodSecurityExpressionHandler;
/**
* @author Rob Winch
* @author Dave Syer
*
*/
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
@Autowired
private SecurityConfiguration securityConfig;
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
return new OAuth2MethodSecurityExpressionHandler();
}
}
===============
org.myt.springframework.config.OAuth2ServerConfig
===============
/*
* Copyright 2002-2013 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.myt.springframework.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
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.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.approval.ApprovalStore;
import org.springframework.security.oauth2.provider.approval.TokenApprovalStore;
import org.springframework.security.oauth2.provider.approval.UserApprovalHandler;
import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
import org.myt.oauth.service.oauth.ExtendedApprovalStoreUserApprovalHandler;
/**
* @author Rob Winch
*
*/
@Configuration
public class OAuth2ServerConfig {
private static final String OAUTH_RESOURCE_ID = "GradleOAuth21";
@Configuration
@Order(10)
protected static class UiResourceConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.requestMatchers().antMatchers("/sync/**","/me", "/oauth/token")
.and()
.authorizeRequests()
.antMatchers("/oauth/token").permitAll()
.antMatchers("/sync/**").access("hasRole('ROLE_USER')")
.antMatchers("/me").access("hasRole('ROLE_USER')")
.antMatchers("/photos").access("hasRole('ROLE_USER')")
.antMatchers("/photos/trusted/**").access("hasRole('ROLE_USER')")
.antMatchers("/photos/user/**").access("hasRole('ROLE_USER')")
.antMatchers("/photos/**").access("hasRole('ROLE_USER')");
// @formatter:on
}
}
@Configuration
@EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources.resourceId(OAUTH_RESOURCE_ID);
}
@Override
public void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.requestMatchers().antMatchers("/sync/**", "/oauth/users/**", "/oauth/clients/**","/me", "/oauth/token")
.and()
.authorizeRequests()
.regexMatchers(HttpMethod.GET,"/oauth/token").permitAll()
.regexMatchers(HttpMethod.POST,"/oauth/token").permitAll()
.antMatchers("/sync").access("#oauth2.hasScope('read') or #oauth2.hasScope('write')")
.antMatchers("/sync/**").access("#oauth2.hasScope('read') or #oauth2.hasScope('write')")
.antMatchers("/photos/trusted/**").access("#oauth2.hasScope('trust')")
.antMatchers("/photos/user/**").access("#oauth2.hasScope('trust')")
.antMatchers("/photos/**").access("#oauth2.hasScope('read')")
.regexMatchers(HttpMethod.DELETE, "/oauth/users/([^/].*?)/tokens/.*")
.access("#oauth2.clientHasRole('ROLE_CLIENT') and (hasRole('ROLE_USER') or #oauth2.isClient()) and #oauth2.hasScope('write')")
.regexMatchers(HttpMethod.GET, "/oauth/clients/([^/].*?)/users/.*")
.access("#oauth2.clientHasRole('ROLE_CLIENT') and (hasRole('ROLE_USER') or #oauth2.isClient()) and #oauth2.hasScope('read')")
.regexMatchers(HttpMethod.GET, "/oauth/clients/.*")
.access("#oauth2.clientHasRole('ROLE_CLIENT') and #oauth2.isClient() and #oauth2.hasScope('read')");
// @formatter:on
}
}
@Configuration
@EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
@Autowired
private TokenStore tokenStore;
@Autowired
private UserApprovalHandler userApprovalHandler;
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// @formatter:off
clients.inMemory().withClient("tonr")
.resourceIds(OAUTH_RESOURCE_ID)
.authorizedGrantTypes("authorization_code", "implicit")
.authorities("ROLE_CLIENT")
.scopes("read", "write")
.secret("mysecret");
/** .and()
.withClient("my-less-trusted-client")
.authorizedGrantTypes("authorization_code", "implicit")
.authorities("ROLE_CLIENT")
.scopes("read", "write", "trust")
**/ // @formatter:on
}
@Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore).userApprovalHandler(userApprovalHandler)
.authenticationManager(authenticationManager);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.realm("client");
}
}
protected static class Stuff {
@Autowired
private ClientDetailsService clientDetailsService;
@Autowired
private TokenStore tokenStore;
@Bean
public ApprovalStore approvalStore() throws Exception {
TokenApprovalStore store = new TokenApprovalStore();
store.setTokenStore(tokenStore);
return store;
}
@Bean
@Lazy
@Scope(proxyMode=ScopedProxyMode.TARGET_CLASS)
public ExtendedApprovalStoreUserApprovalHandler userApprovalHandler() throws Exception {
ExtendedApprovalStoreUserApprovalHandler handler = new ExtendedApprovalStoreUserApprovalHandler();
handler.setApprovalStore(approvalStore());
handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
handler.setClientDetailsService(clientDetailsService);
handler.setUseApprovalStore(true);
return handler;
}
}
}
=============
org.myt.springframework.config.SecurityConfiguration
=============
package org.myt.springframework.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//TODO Change it after user story test. See also login.jsp
auth.inMemoryAuthentication().withUser("user1@demo.com").password("user2").roles("USER").and().withUser("user2@demo.com")
.password("user2").roles("USER");
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/webjars/**", "/images/**", "/oauth/uncache_approvals", "/oauth/cache_approvals");
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http.authorizeRequests().regexMatchers(HttpMethod.GET, "/oauth/token").permitAll()
.regexMatchers(HttpMethod.POST,"/oauth/token").permitAll()
.antMatchers("/sync/**").permitAll()
.anyRequest().authenticated()
.and()
.authorizeRequests().antMatchers("/login").permitAll().and()
.authorizeRequests()
.anyRequest().hasRole("USER")
.and()
.exceptionHandling()
.accessDeniedPage("/login.jsp?authorization_error=true")
.and()
// TODO: put CSRF protection back into this endpoint
.csrf()
.requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/authorize")).disable()
.logout()
.logoutSuccessUrl("/index.jsp")
.logoutUrl("/logout.do")
.and()
.formLogin()
.usernameParameter("j_username")
.passwordParameter("j_password")
.failureUrl("/login.jsp?authentication_error=true")
.loginPage("/login").permitAll()
.loginProcessingUrl("/login.do");// Seems to be related the default MVC controller
// @formatter:on
}
}
=======
org.myt.springframework.config.ServletInitializer
=======
/*
* Copyright 2013-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.myt.springframework.config;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import org.springframework.util.ClassUtils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.DelegatingFilterProxy;
import org.springframework.web.servlet.support.AbstractDispatcherServletInitializer;
/**
* @author Dave Syer
*
*/
public class ServletInitializer extends AbstractDispatcherServletInitializer {
@Override
protected WebApplicationContext createServletApplicationContext() {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.scan(ClassUtils.getPackageName(getClass()));
return context;
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
@Override
protected WebApplicationContext createRootApplicationContext() {
return null;
}
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
super.onStartup(servletContext);
DelegatingFilterProxy filter = new DelegatingFilterProxy("springSecurityFilterChain");
filter.setContextAttribute("org.springframework.web.servlet.FrameworkServlet.CONTEXT.dispatcher");
servletContext.addFilter("springSecurityFilterChain", filter).addMappingForUrlPatterns(null, false, "/*");
}
}
======
org.myt.springframework.config.WebMvcConfig
======
package org.myt.springframework.config;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.Ordered;
import org.springframework.http.MediaType;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.approval.ApprovalStore;
import org.springframework.security.oauth2.provider.token.ConsumerTokenServices;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.web.accept.ContentNegotiationManagerFactoryBean;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.ContentNegotiatingViewResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.json.MappingJackson2JsonView;
import org.myt.oauth.service.PhotoInfo;
import org.myt.oauth.service.PhotoService;
import org.myt.oauth.service.impl.PhotoServiceImpl;
import org.myt.oauth.service.mvc.AccessConfirmationController;
import org.myt.oauth.service.mvc.AdminController;
import org.myt.oauth.service.mvc.PhotoController;
import org.myt.oauth.service.mvc.PhotoServiceUserController;
import org.myt.oauth.service.oauth.ExtendedApprovalStoreUserApprovalHandler;
@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
@Bean
public ContentNegotiatingViewResolver contentViewResolver() throws Exception {
ContentNegotiationManagerFactoryBean contentNegotiationManager = new ContentNegotiationManagerFactoryBean();
contentNegotiationManager.addMediaType("json", MediaType.APPLICATION_JSON);
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/jsp/");
viewResolver.setSuffix(".jsp");
MappingJackson2JsonView defaultView = new MappingJackson2JsonView();
defaultView.setExtractValueFromSingleKeyModel(true);
ContentNegotiatingViewResolver contentViewResolver = new ContentNegotiatingViewResolver();
contentViewResolver.setContentNegotiationManager(contentNegotiationManager.getObject());
contentViewResolver.setViewResolvers(Arrays.<ViewResolver>asList(viewResolver));
contentViewResolver.setDefaultViews(Arrays.<View>asList(defaultView));
return contentViewResolver;
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
}
@Bean
public PhotoServiceUserController photoServiceUserController(PhotoService photoService) {
PhotoServiceUserController photoServiceUserController = new PhotoServiceUserController();
return photoServiceUserController;
}
@Bean
public PhotoController photoController(PhotoService photoService) {
PhotoController photoController = new PhotoController();
photoController.setPhotoService(photoService);
return photoController;
}
@Bean
public AccessConfirmationController accessConfirmationController(ClientDetailsService clientDetailsService, ApprovalStore approvalStore) {
AccessConfirmationController accessConfirmationController = new AccessConfirmationController();
accessConfirmationController.setClientDetailsService(clientDetailsService);
accessConfirmationController.setApprovalStore(approvalStore);
return accessConfirmationController;
}
@Bean
public PhotoServiceImpl photoServices() {
List<PhotoInfo> photos = new ArrayList<PhotoInfo>();
photos.add(createPhoto("1", "marissa"));
photos.add(createPhoto("2", "paul"));
photos.add(createPhoto("3", "marissa"));
photos.add(createPhoto("4", "paul"));
photos.add(createPhoto("5", "marissa"));
photos.add(createPhoto("6", "paul"));
PhotoServiceImpl photoServices = new PhotoServiceImpl();
photoServices.setPhotos(photos);
return photoServices;
}
@Bean
public AdminController adminController(TokenStore tokenStore, ConsumerTokenServices tokenServices,
ExtendedApprovalStoreUserApprovalHandler userApprovalHandler) {
AdminController adminController = new AdminController();
adminController.setTokenStore(tokenStore);
adminController.setTokenServices(tokenServices);
adminController.setUserApprovalHandler(userApprovalHandler);
return adminController;
}
private PhotoInfo createPhoto(String id, String userId) {
PhotoInfo photo = new PhotoInfo();
photo.setId(id);
photo.setName("photo" + id + ".jpg");
photo.setUserId(userId);
photo.setResourceURL("/impl/resources/" + photo.getName());
return photo;
}
@Override
public void configureDefaultServletHandling(
DefaultServletHandlerConfigurer configurer) {
configurer.enable();
}
}
=====
感谢您的帮助
答案 0 :(得分:0)
您需要使用基本身份验证来获取访问代码的请求。使用客户端ID作为用户名,使用客户端密码作为密码。