spring-oauth

来源:互联网 发布:美国黑人矛盾 知乎 编辑:程序博客网 时间:2024/05/20 06:24

1:项目入门DEMO

1:POM文件

<projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0http://maven.apache.org/xsd/maven-4.0.0.xsd">

   <modelVersion>4.0.0</modelVersion>

 

   <groupId>com.hujiang.boot</groupId>

   <artifactId>auth-service</artifactId>

   <version>0.0.1-SNAPSHOT</version>

   <packaging>jar</packaging>

 

   <name>auth-service</name>

   <url>http://maven.apache.org</url>

 

   <parent>

      <groupId>org.springframework.boot</groupId>

      <artifactId>spring-boot-starter-parent</artifactId>

      <version>1.2.3.RELEASE</version>

      <relativePath/>

   </parent>

 

   <dependencies>

      <dependency>

         <groupId>org.springframework.boot</groupId>

         <artifactId>spring-boot-starter-security</artifactId>

      </dependency>

      <dependency>

         <groupId>org.springframework.security.oauth</groupId>

         <artifactId>spring-security-oauth2</artifactId>

         <version>2.0.7.RELEASE</version>

      </dependency>

      <dependency>

         <groupId>org.springframework.boot</groupId>

         <artifactId>spring-boot-starter-web</artifactId>

      </dependency>

   </dependencies>

</project>

 

 

 

 

 

 

 

2:Main方法

@Configuration

@ComponentScan

@EnableAutoConfiguration

@RestController

@SessionAttributes("authorizationRequest")

@EnableResourceServer

public class AuthserverApplication extends WebMvcConfigurerAdapter {

 

   public static void main(String[] args) {

      SpringApplication.run(AuthserverApplication.class,args);

   }

 

   @RequestMapping("/hello")

   public String hello() {

      return "hello";

   }

 

  

   @Configuration

   @EnableAuthorizationServer

   protected static class OAuth2Config extends AuthorizationServerConfigurerAdapter {

 

      @Autowired

      private AuthenticationManagerauthenticationManager;

     

      @Override

      public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

         clients.inMemory().withClient("acme").secret("acmesecret")

            .authorizedGrantTypes("client_credentials").scopes("openid");

      }

 

      @Override

      public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

         endpoints.authenticationManager(authenticationManager);

      }

 

      @Override

      public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {

      oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");

      }

 

   }

}

 

3:测试:

通过curl http://localhost:8080/hello访问,返回认证失败

{"error":"unauthorized","error_description":"Fullauthentication is required to access this resource"}

 

先拿到访问TOKEN

curl -v -X POST"acme:acmesecret@localhost:8080/oauth/token?grant_type=client_credentials"

{"access_token":"b92fd988-d95b-427c-84bf-65da969e45f0","token_type":"bearer","expires_in":42933,"scope":"openid"}

 

请求接口:

curl -H "Authorization:Bearerb92fd988-d95b-427c-84bf-65da969e45f0" http://localhost:8080/hello

或者curl http://localhost:8080/hello?access_token=b92fd988-d95b-427c-84bf-65da969e45f0

返回hello

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

2:通过http请求,验证TOKEN的有效性

1:默认配置

验证token

正确:

失败:


总结:这种方式不适合我们项目,A调用B时,不能把A的client_id和secret也传递给B。

如果不传递,默认情况下/oauth/check_token是受保护的接口;如果B不需要调用其他的服务,是不需要注册的,所以直接调用该接口,会提示未认证。

 

2:修改配置,/oauth/check_token暴露出去,不受oauth保护

applicationContext.properties添加如下配置

security.ignored=/welcome,/oauth/check_token


正确:


失败:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

3:如何配置JDBC数据库

http://andaily.com/spring-oauth-server/db_table_description.html

1:代码修改

2:创建数据库表

-- used in tests that use HSQL

create table oauth_client_details (

 client_id VARCHAR(256) PRIMARY KEY,

 resource_ids VARCHAR(256),

 client_secret VARCHAR(256),

 scope VARCHAR(256),

 authorized_grant_types VARCHAR(256),

 web_server_redirect_uri VARCHAR(256),

 authorities VARCHAR(256),

 access_token_validity INTEGER,

 refresh_token_validity INTEGER,

 additional_information VARCHAR(4096),

 autoapprove VARCHAR(256)

);

 

create table oauth_client_token (

 token_id VARCHAR(256),

 token LONGVARBINARY,

 authentication_id VARCHAR(256) PRIMARY KEY,

 user_name VARCHAR(256),

 client_id VARCHAR(256)

);

 

create table oauth_access_token (

 token_id VARCHAR(256),

 token LONGVARBINARY,

 authentication_id VARCHAR(256) PRIMARY KEY,

 user_name VARCHAR(256),

 client_id VARCHAR(256),

 authentication LONGVARBINARY,

 refresh_token VARCHAR(256)

);

 

create table oauth_refresh_token (

 token_id VARCHAR(256),

 token LONGVARBINARY,

 authentication LONGVARBINARY

);

 

create table oauth_code (

 code VARCHAR(256), authentication LONGVARBINARY

);

 

create table oauth_approvals (

         userIdVARCHAR(256),

         clientIdVARCHAR(256),

         scopeVARCHAR(256),

         statusVARCHAR(10),

         expiresAtTIMESTAMP,

         lastModifiedAtTIMESTAMP

);

 

 

-- customized oauth_client_details table

create table ClientDetails (

 appId VARCHAR(256) PRIMARY KEY,

 resourceIds VARCHAR(256),

 appSecret VARCHAR(256),

 scope VARCHAR(256),

 grantTypes VARCHAR(256),

  redirectUrlVARCHAR(256),

 authorities VARCHAR(256),

 access_token_validity INTEGER,

 refresh_token_validity INTEGER,

 additionalInformation VARCHAR(4096),

 autoApproveScopes VARCHAR(256)

);

 

3:测试

没有数据时:

 

执行SQL插入一条记录:

insert oauth_client_details(client_id,client_secret,authorized_grant_types,scope)

values("acme","acmesecret","client_credentials","openid");

 

 

再次执行:

 

 

 

 

 

4:如何在运行时动态的修改客户端

http://projects.spring.io/spring-security-oauth/docs/oauth2.html   (Configuring ClientDetails)

 

 

 

 

 

 

 

5:如何将TOKEN存库

http://projects.spring.io/spring-security-oauth/docs/oauth2.html(Managing Tokens)

 

@Configuration

@EnableResourceServer

protected static class ResourceServer extendsResourceServerConfigurerAdapter {

 

   @Autowired

   private TokenStoretokenStore;

 

   @Override

   public voidconfigure(ResourceServerSecurityConfigurer resources) throws Exception {

      resources.tokenStore(tokenStore);

   }

 

   @Override

   public void configure(HttpSecurity http)throws Exception {

      http.authorizeRequests().anyRequest().authenticated();

   }

}

 

 

@Bean

publicJdbcTokenStore tokenStore() {

   return new JdbcTokenStore(dataSource);

}

 

@Override

public voidconfigure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

   endpoints.tokenStore(tokenStore());

}

 

 

 

6:如何把请求放到URL中访问

在前面的demo中,获取TOKEN,都是通过curl -v -X POST"acme:acmesecret@localhost:8080/oauth/token?grant_type=client_credentials"拿到的,如果使用我们熟悉的get方式 curlhttp://localhost:8080/uaa/oauth/token?grant_type=client_credentials&client_id=acme&client_secret=acmesecret或者post方式curl -d"grant_type=client_credentials&client_id=acme&client_secret=acmesecret"http://localhost:8080/uaa/oauth/token。会抛出一样的错误提示。

 

修改我们上面的Oauth2Config类

重启服务器,再次通过get,或者post提交试试.

POST请求

GET请求依然不支持

 

 

 

 

 

 

 

 

 

 

 

 

7:SCOPE的使用

我们知道,Oauth2.0中,生成TOKEN之后,就可以拿着TOKEN来访问我受保护的resource了。但如果有个url,比如/A/B地址,我只希望指定的客户端才能访问,要如何操作呢。

 

1:数据库对应的client

2:修改ResourceServer配置

 

测试:

1:使用ADMIN对应的客户端acme进行测试

请求/uaa/oauth/token地址,获取TOKEN


用生成的TOKEN,访问hello

 

 

 

2:使用CLIENT对应的客户端acme2进行测试

请求/uaa/oauth/token地址,获取TOKEN

用生成的TOKEN,访问hello

 

 

 

 

8:如何重写ClientDetailsService

 

从源码可以看到,ClientDetailsService的实现,来自于ClientDetailsServiceConfigurer的配置,而ClientDetailsServiceConfigurer只提供了inMemory和jdbc两种方法。比如,要从远程的restapi获取client信息,我们可以自己实现一个ClientDetailsService,不用默认的。

 

 

 

 

 

 

 

 

 

9:扩展TOKEN内容

在例子8中,我们向Client中,添加了自定义的group和client。跟踪TokenEndpoint源码会发现,虽然OAuth2AccessToken提供了getAdditionalInformation方法,用来对Token进行扩展,但是源码中并没有将Client的扩展信息放入Token中,所以最终/oauth/token返回的json中,是没有group和role信息的。跟踪源码,会发现生成Token是,提供了对token的扩展。


 

 

下面是接口实现


 

 

 

10:如何修改Header信息

默认情况,通过curl -H "Authorization:Bearer8bc6275d-ed2d-442e-b7b4-aa2fab536c4e" http://localhost:9003/uaa/v1/hello方式访问资源

 

 

 

 

1:把/oauth/token配置到了security.ignored=/oauth/check_token,/oauth/token


0 0