我想用0腿(因此没有请求或访问令牌)OAuth 1.0设置Spring
Boot应用程序。我一直在挖掘一段时间以尝试查找示例,而我主要停留在如何使用新样式(无xml)配置方面。
现在,我只想得到一个简单的用例,其中只有1个路径(/ oauth)受OAuth保护(其他所有内容都是敞开的),并且它使用自定义的
ConsumerDetailsService (有关该代码的简单版本,请参见下文)。
这是我的 WebSecurityConfigurerAdapter
(位于Application.java旁边的SecurityConfiguration.java,我认为这是在Spring
Boot应用程序中配置此类操作的正确方法)。我很确定我缺少提供程序配置(如http://projects.spring.io/spring-
security-oauth/docs/oauth1.html中所述),但是我的反复试验没有产生结果。
@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
// 0-Legged OAuth on the /oauth and /lti paths only
http.requestMatchers().antMatchers("/oauth"); // .and().... what?
// ??? something must be missing here - provider?
}
}
我的maven pom.xml中也有这个:
<!-- security and oauth -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- OAuth -->
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
我的自定义ConsumerDetailsService
@Component
public class LTIConsumerDetailsService implements ConsumerDetailsService {
@Override
public ConsumerDetails loadConsumerByConsumerKey(String consumerKey) throws OAuthException {
BaseConsumerDetails cd;
// TODO really lookup the key and related consumer details, for sample here we just hardcoded
if ("key".equals(consumerKey)) {
cd = new BaseConsumerDetails();
cd.setConsumerKey(consumerKey);
cd.setSignatureSecret(new SharedConsumerSecretImpl("secret"));
cd.setConsumerName("Sample consumerName");
cd.setRequiredToObtainAuthenticatedToken(false); // no token required (0-legged)
cd.setResourceDescription("Sample consumer details - AZ");
cd.setResourceName("Sample resourceName");
} else {
throw new OAuthException("For this example, key must be 'key'");
}
return cd;
}
}
任何有关如何使此工作正常运行的建议或指向Spring Boot OAuth 1.0代码的指针将不胜感激。请注意,我已经尝试查看单独的spring
boot安全性和OAuth指南,但无法成功合并它们。
这是我如何通过Java Config在spring-boot 1.1.4中获得0腿OAuth 1.0的工作方式。
注意:就我而言,我只希望OAuth保护单个路径(/ oauth /
**),因此,如果希望保护所有内容,则可以简化其中的某些部分。您可以在这里查看我的完整代码:https://github.com/azeckoski/lti_starter
一旦拥有了下面显示的最少部分,您就应该能够运行spring-boot应用程序,并使用ConsumerKey:key和Secret:secret在/
oauth处触发OAuth 1.0兼容请求,并成功加载路径。
重要说明
:(1)不要只是将ZeroLeggedOAuthProviderProcessingFilter声明为Bean,否则将影响所有路径(它将自动被spring拾取)。(2)如果要访问,则必须存在NoAuthConfigurationAdapter受保护路径之外的安全数据(在本例中为/
oauth)
@ComponentScan
@Configuration
@EnableAutoConfiguration
@EnableWebMvcSecurity // enable spring security and web mvc hooks
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class Application extends WebMvcConfigurerAdapter {
final static Logger log = LoggerFactory.getLogger(Application.class);
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
// Spring Security
@Autowired
@Order(Ordered.HIGHEST_PRECEDENCE + 10)
@SuppressWarnings("SpringJavaAutowiringInspection")
public void configureSimpleAuthUsers(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("admin").password("admin").roles("ADMIN", "USER")
.and().withUser("user").password("user").roles("USER");
}
@Configuration
@Order(1) // HIGHEST
public static class OAuthSecurityConfigurerAdapter extends WebSecurityConfigurerAdapter {
private ZeroLeggedOAuthProviderProcessingFilter zeroLeggedOAuthProviderProcessingFilter;
@Autowired
OAuthConsumerDetailsService oauthConsumerDetailsService;
@Autowired
OAuthAuthenticationHandler oauthAuthenticationHandler;
@Autowired
OAuthProcessingFilterEntryPoint oauthProcessingFilterEntryPoint;
@Autowired
OAuthProviderTokenServices oauthProviderTokenServices;
@PostConstruct
public void init() {
zeroLeggedOAuthProviderProcessingFilter = new ZeroLeggedOAuthProviderProcessingFilter(oauthConsumerDetailsService, new InMemoryNonceServices(), oauthProcessingFilterEntryPoint, oauthAuthenticationHandler, oauthProviderTokenServices);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/oauth/**")
.addFilterBefore(zeroLeggedOAuthProviderProcessingFilter, UsernamePasswordAuthenticationFilter.class)
.authorizeRequests().anyRequest().hasRole("OAUTH");
}
}
@Order(45) // LOW
@Configuration
public static class BasicAuthConfigurationAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/basic/**").authorizeRequests().anyRequest().authenticated()
.and().httpBasic();
}
}
@Order(67) // LOWEST
@Configuration
public static class NoAuthConfigurationAdapter extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**").authorizeRequests().anyRequest().permitAll();
}
}
// OAuth beans
public static class OAuthProcessingFilterEntryPointImpl extends OAuthProcessingFilterEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
log.info("OAuth FILTER Failure (commence), req=" + request + ", ex=" + authException);
// Called when there is an OAuth Auth failure, authException may be InsufficientAuthenticationException
super.commence(request, response, authException);
}
}
@Bean(name = "oauthAuthenticationEntryPoint")
public OAuthProcessingFilterEntryPoint oauthAuthenticationEntryPoint() {
return new OAuthProcessingFilterEntryPointImpl();
}
@Bean(name = "oauthProviderTokenServices")
public OAuthProviderTokenServices oauthProviderTokenServices() {
// NOTE: we don't use the OAuthProviderTokenServices for 0-legged but it cannot be null
return new InMemoryProviderTokenServices();
}
public static class ZeroLeggedOAuthProviderProcessingFilter extends ProtectedResourceProcessingFilter {
ZeroLeggedOAuthProviderProcessingFilter(OAuthConsumerDetailsService oAuthConsumerDetailsService, OAuthNonceServices oAuthNonceServices, OAuthProcessingFilterEntryPoint oAuthProcessingFilterEntryPoint, OAuthAuthenticationHandler oAuthAuthenticationHandler, OAuthProviderTokenServices oAuthProviderTokenServices) {
super();
log.info("CONSTRUCT Zero Legged OAuth provider");
setAuthenticationEntryPoint(oAuthProcessingFilterEntryPoint);
setAuthHandler(oAuthAuthenticationHandler);
setConsumerDetailsService(oAuthConsumerDetailsService);
setNonceServices(oAuthNonceServices);
setTokenServices(oAuthProviderTokenServices);
//setIgnoreMissingCredentials(false); // die if OAuth params are not included
}
}
}
@Component
public class OAuthConsumerDetailsService implements ConsumerDetailsService {
final static Logger log = LoggerFactory.getLogger(OAuthConsumerDetailsService.class);
@Override
public ConsumerDetails loadConsumerByConsumerKey(String consumerKey) throws OAuthException {
BaseConsumerDetails cd;
// NOTE: really lookup the key and secret, for the sample here we just hardcoded
if ("key".equals(consumerKey)) {
// allow this oauth request
cd = new BaseConsumerDetails();
cd.setConsumerKey(consumerKey);
cd.setSignatureSecret(new SharedConsumerSecretImpl("secret"));
cd.setConsumerName("Sample");
cd.setRequiredToObtainAuthenticatedToken(false); // no token required (0-legged)
cd.getAuthorities().add(new SimpleGrantedAuthority("ROLE_OAUTH")); // add the ROLE_OAUTH (can add others as well)
log.info("OAuth check SUCCESS, consumer key: " + consumerKey);
} else {
// deny - failed to match
throw new OAuthException("For this example, key must be 'key'");
}
return cd;
}
}
最后一部分对于根据来自OAuth请求的数据定义实际用户(和Principal)很重要。这将取决于您在本地处理事物的方式而有所不同,但这是如何执行此操作的示例。
@Component
public class MyOAuthAuthenticationHandler implements OAuthAuthenticationHandler {
final static Logger log = LoggerFactory.getLogger(MyOAuthAuthenticationHandler.class);
static SimpleGrantedAuthority userGA = new SimpleGrantedAuthority("ROLE_USER");
static SimpleGrantedAuthority adminGA = new SimpleGrantedAuthority("ROLE_ADMIN");
@Override
public Authentication createAuthentication(HttpServletRequest request, ConsumerAuthentication authentication, OAuthAccessProviderToken authToken) {
Collection<GrantedAuthority> authorities = new HashSet<>(authentication.getAuthorities());
// attempt to create a user Authority
String username = request.getParameter("username");
if (StringUtils.isBlank(username)) {
username = authentication.getName();
}
// NOTE: you should replace this block with your real rules for determining OAUTH ADMIN roles
if (username.equals("admin")) {
authorities.add(userGA);
authorities.add(adminGA);
} else {
authorities.add(userGA);
}
Principal principal = new NamedOAuthPrincipal(username, authorities,
authentication.getConsumerCredentials().getConsumerKey(),
authentication.getConsumerCredentials().getSignature(),
authentication.getConsumerCredentials().getSignatureMethod(),
authentication.getConsumerCredentials().getSignatureBaseString(),
authentication.getConsumerCredentials().getToken()
);
Authentication auth = new UsernamePasswordAuthenticationToken(principal, null, authorities);
return auth;
}
public static class NamedOAuthPrincipal extends ConsumerCredentials implements Principal {
public String name;
public Collection<GrantedAuthority> authorities;
public NamedOAuthPrincipal(String name, Collection<GrantedAuthority> authorities, String consumerKey, String signature, String signatureMethod, String signatureBaseString, String token) {
super(consumerKey, signature, signatureMethod, signatureBaseString, token);
this.name = name;
this.authorities = authorities;
}
@Override
public String getName() {
return name;
}
public Collection<? extends GrantedAuthority> getAuthorities() {
return authorities;
}
}
}
@Controller
@RequestMapping("/oauth")
public class OAuthController extends BaseController {
@RequestMapping({"", "/"})
public String home(HttpServletRequest req, Principal principal, Model model) {
return "home"; // name of the template
}
}
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- security and oauth -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!-- OAuth -->
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth</artifactId>
<version>2.0.2.RELEASE</version>
</dependency>
我知道在DispatcherServlet之外使用请求范围bean需要一些配置,并且已经阅读了http://docs.spring.io/spring/docs/4.0.x/spring-framework-reference/html/beans.html#beans-factory-scopes-oth,但是还没有成功: 对于Servlet3.0+,这可以通过WebApplicationIni
我在学习Spring Boot时遇到了一些编码问题;我想添加一个像Spring3.x那样的CharacterEncodingFilter。就像这样:
<dependencyManagement> <dependencies> <dependency> <!--Import dependency management from SpringBoot--> <groupId>org.springframework.boot</groupId>
问题内容: 我正在尝试使用Maven 3 在Spring Boot应用程序中设置活动配置文件。在我的pom.xml中,将默认的活动配置文件和属性spring.profiles.active设置 为development: 但是每次我运行应用程序时,都会在日志中收到以下消息: 并且将SpringBoot配置文件设置为默认值(读取application.properties而不是application
null 非常感谢你的帮助
我试图在使用Maven3的Spring Boot应用程序中设置一个活动概要文件。 在我的pom.xml中,我将默认的活动概要文件和属性Spring.profiles.active设置为development: 但是每次运行我的应用程序时,我都会在日志中收到以下消息: 并且SpringBoot配置文件设置为default(读取application.properties,而不是application