在没有 XML 配置的情况下实现 Spring Security Oauth

Posted

技术标签:

【中文标题】在没有 XML 配置的情况下实现 Spring Security Oauth【英文标题】:Implementing Spring Security Oauth without XML configuration 【发布时间】:2014-11-18 05:04:27 【问题描述】:

我正在尝试构建一个基本的 REST 服务,该服务受 Spring Security 保护,具有 OAuth 2.0 身份验证和授权。

我试图限制所涉及的元素,因此我没有复制粘贴依赖于 Spring Beans、Spring MVC 等的 Spring Security Oath XML 配置,而是直接使用 Spring Security Oauth 类。

我在尝试从 /oauth/token 获取访问令牌时遇到了问题。我可能缺少一些基本的东西,但是 Spring Security 和 Spring Security Oauth 都很难让我理解,而且我似乎找不到一个不需要使用额外框架的示例或教程。

谁能看出我哪里出错了?

RestService.java

@Path("/members")
public class RestService 

    @Secured("ROLE_USER")
    @GET
    @Path("/id")
    @Produces(MediaType.TEXT_PLAIN)
    public Response readMember(@PathParam("id") String id) 

        String output;
        if(Integer.valueOf(id) < members.size())
        
            output = members.get(Integer.valueOf(id)).toString();
        
        else
        
            output = "No such member.";
        

        return Response.status(200).entity(output).build();
    

OAuthServices.java

public class OAuthServices 

    static private DefaultTokenServices tokenServices = new DefaultTokenServices();
    static private InMemoryClientDetailsService clientDetailsService = new InMemoryClientDetailsService();

    static 
        Map<String, ClientDetails> clientDetailsStore = new HashMap<String, ClientDetails>();
        BaseClientDetails clientDetails = new BaseClientDetails("client", "resource", null, null, "read,write");
        clientDetailsStore.put("client", clientDetails);
        clientDetailsService.setClientDetailsStore(clientDetailsStore);
    

    public static DefaultTokenServices getTokenServices() 
        return tokenServices;
    

    public static InMemoryClientDetailsService getClientDetailsService() 
        return clientDetailsService;
    

SecurityConfig.java

@EnableAuthorizationServer
@EnableWebSecurity
@Configuration
@EnableGlobalMethodSecurity(securedEnabled=true)
public class SecurityConfig extends WebSecurityConfigurerAdapter implements AuthorizationServerConfigurer 

    @Configuration
    protected static class AuthenticationConfiguration extends
            GlobalAuthenticationConfigurerAdapter 

        @Override
        public void init(AuthenticationManagerBuilder auth) throws Exception 
            auth
                    .inMemoryAuthentication()
                    .withUser("user").password("password").roles("USER")
                    .and()
                    .withUser("admin").password("password").roles("USER", "ADMIN");
        

    

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security)
            throws Exception 
        // TODO Auto-generated method stub

    

    @Override
    public void configure(ClientDetailsServiceConfigurer clients)
            throws Exception 
        // TODO Auto-generated method stub

    

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints)
            throws Exception 
        // TODO Auto-generated method stub

    

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
    <servlet>
        <servlet-name>jersey-helloworld-servlet</servlet-name>
        <servlet-class>
                     org.glassfish.jersey.servlet.ServletContainer
                </servlet-class>
                <init-param>
            <param-name>jersey.config.server.provider.packages</param-name>
            <param-value>com.excentus.springsecurity.rest.test</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>jersey-helloworld-servlet</servlet-name>
        <url-pattern>/rest/*</url-pattern>
    </servlet-mapping>
</web-app>

【问题讨论】:

有很多代码需要人们去查看。如果可能的话,我建议更简洁地说明您的问题。 我认为如果有必要将它放在那里作为参考会很有用,尽管其中大部分不应该是相关的。如果不赞成,我可以减少它。 【参考方案1】:

我可以看到 2 个错误(也许不是全部)。

    您正在使用web.xml,但那里没有定义 Spring Security 过滤器。这是样板代码,但您必须这样做(例如,除非您切换到使用 Spring Boot 编写应用程序的更现代的方式)。示例(来自docs):

    springSecurityFilterChain org.springframework.web.filter.DelegatingFilterProxy

    springSecurityFilterChain /*

    您已经实现了AuthorizationServerConfigurer,但没有实现它的任何方法。您至少需要提供客户详细信息,例如(来自[集成测试(https://github.com/spring-projects/spring-security-oauth/blob/master/tests/annotation/vanilla/src/main/java/demo/Application.java)):

        @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception 
        clients.inMemory()
            .withClient("my-trusted-client")
                .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
                .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
                .scopes("read", "write", "trust")
                .resourceIds("oauth2-resource")
                .accessTokenValiditySeconds(60);
    
    

您的静态便利类 OAuthServices 也是一种反模式,但它不会破坏任何东西(我也没有看到它在任何地方使用,但可能错过了)。

【讨论】:

以上是关于在没有 XML 配置的情况下实现 Spring Security Oauth的主要内容,如果未能解决你的问题,请参考以下文章

在没有插件 web.xml 问题的情况下配置 Spring Security

在没有XML的情况下在Spring 4.1.5中配置事务

Spring学习bean装配详解之 XML方式配置

Spring+MyBatis纯注解零XML整合

spring中定时任务的多种实现

如何在没有spring boot的情况下使用spring批处理的java配置?