当前位置: 首页 > 面试题库 >

在Spring Boot中配置0足OAuth 1.0

燕实
2023-03-14
问题内容

我想用0腿(因此没有请求或访问令牌)OAuth 1.0设置Spring
Boot应用程序。我一直在挖掘一段时间以尝试查找示例,而我主要停留在如何使用新样式(无xml)配置方面。

现在,我只想得到一个简单的用例,其中只有1个路径(/ oauth)受OAuth保护(其他所有内容都是敞开的),并且它使用自定义的
ConsumerDetailsS​​ervice (有关该代码的简单版本,请参见下文)。

这是我的 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>

我的自定义ConsumerDetailsS​​ervice

@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
        }
    }
}

OAuthConsumerDetailsS​​ervice.java

@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;
    }

}

MyOAuthAuthenticationHandler.java

最后一部分对于根据来自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;
        }
    }
}

OAuthController.java

@Controller
@RequestMapping("/oauth")
public class OAuthController extends BaseController {

    @RequestMapping({"", "/"})
    public String home(HttpServletRequest req, Principal principal, Model model) {
        return "home"; // name of the template
    }
}

pom.xml(maven-仅关键部分)

<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