Spring Security Oauth2 授权服务开发

集成开发环境

·开发工具:Eclipse/Myeclipse/IntelliJ IDEA 任选其一

·运行环境:jdk1.7及以上版本

·数据库:MySQL

spring-security-oauth2源码

·github地址:https://github.com/spring-projects/spring-security-oauth.git

构建授权服务

1、使用eclipse新建一个名称为“oauth2-server”maven项目,将其pom.xml配置文件修改为如下:

<project xmlns="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.0 http://maven.apache.org/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>oauth2-server</groupId>

    <artifactId>oauth2-server</artifactId>

    <packaging>war</packaging>

    <version>0.0.1-SNAPSHOT</version>

    <name>oauth2-server Maven Webapp</name>

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

    <parent>

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

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

        <version>1.5.8.RELEASE</version>

    </parent>

    <dependencies>

        <dependency>

            <groupId>org.springframework.cloud</groupId>

            <artifactId>spring-cloud-security</artifactId>

            <version>1.2.1.RELEASE</version>

        </dependency>

        <dependency>

            <groupId>fort-spring-security-oauth2</groupId>

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

            <version>0.0.1-SNAPSHOT</version>

        </dependency>

        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->

        <dependency>

            <groupId>mysql</groupId>

            <artifactId>mysql-connector-java</artifactId>

            <version>5.1.38</version>

        </dependency>

        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-dbcp2 -->

        <dependency>

            <groupId>org.apache.commons</groupId>

            <artifactId>commons-dbcp2</artifactId>

            <version>2.1.1</version>

        </dependency>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->

        <dependency>

            <groupId>org.springframework</groupId>

            <artifactId>spring-jdbc</artifactId>

            <version>4.3.9.RELEASE</version>

        </dependency>

    </dependencies>

    <build>

        <finalName>oauth2-server</finalName>

    </build>

</project>

2、新建程序启动类“Application.java”,如下所示:

@SpringBootApplication

@EnableAuthorizationServer

public class Application {



    public static void main(String[] args) {

        SpringApplication.run(Application.class, args);

    }

}

3、新建“AuthServerConfig.java”类继承“AuthorizationServerConfigurerAdapter”类初始化授权服务所需要的信息,如下所示:

@Configuration

public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {



    @Autowired

    private DataSource dataSource;



    @Autowired

    private AuthenticationManager authenticationManager;



    @Override

    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

        clients.jdbc(dataSource);

    }



    @Override

    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

        endpoints.tokenStore(new JdbcTokenStore(dataSource)).authenticationManager(authenticationManager).userDetailsService(userDetailsService());

    }



    @Override

    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {

        security.checkTokenAccess("permitAll()").allowFormAuthenticationForClients();

    }



    @Bean

    public UserDetailsService userDetailsService() {

        InMemoryUserDetailsManager manager = new InMemoryUserDetailsManager();

        manager.createUser(User.withUsername("user").password("123").authorities("ROLE_USER", "ROLE_RESOURCE", "ROLE_API").build());

        return manager;

    }

}

4、新建“DataSourceConfig”类初始化数据源,如下所示:

@Configuration

public class DataSourceConfig {

   

    @Bean(name="dataSource")

    @ConfigurationProperties(prefix="spring.datasource")

    public DataSource getDataSource() {

        return DataSourceBuilder.create(BasicDataSource.class.getClassLoader()).build();

    }

   

}

 

5、新建“application.yml”配置文件,内容如下:

spring:

  datasource:

    url: jdbc:mysql://host:3306/db_name?useUnicode=true&characterEncoding=UTF-8

    username: root

    password: 2wsx3edc

    driverClassName: com.mysql.jdbc.Driver

数据库表结构

由于本示例需要将token以及client_id以及client_secret保存在数据库中,以便重启后还可再次使用,所以采用了mysql存储,有关表结构信息请参考“JdbcTokenStore.java”和“JdbcClientDetailsService.java”

本示例需要构建三个数据库表,分别为:

1、“oauth_access_token”表用来存储用户的token信息;

2、“oauth_client_details”表用来存储应用的client_id以及client_secret等信息;

3、“oauth_refresh_token”表用来存储刷新token操作的信息。

数据库表结构如下:

CREATE TABLE `oauth_access_token` (
  `token_id` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `token` blob,
  `authentication_id` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `user_name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `client_id` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `authentication` blob,
  `refresh_token` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

CREATE TABLE `oauth_client_details` (
  `client_id` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `client_secret` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `resource_ids` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `scope` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `authorized_grant_types` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `web_server_redirect_uri` text COLLATE utf8_unicode_ci,
  `authorities` text COLLATE utf8_unicode_ci,
  `access_token_validity` int(11) DEFAULT NULL,
  `refresh_token_validity` int(11) DEFAULT NULL,
  `additional_information` text COLLATE utf8_unicode_ci,
  `autoapprove` text COLLATE utf8_unicode_ci
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

CREATE TABLE `oauth_refresh_token` (
  `token_id` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `token` blob,
  `authentication` blob
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci

启动授权服务

启动授权服务是很简单的,您只需要运行“Application.java”即可启动授权服务。

测试授权服务

授权模式

oauth2规范中具备了四种授权模式,分别如下:

·授权码模式:authorization code

·简化模式:implicit

·密码模式:resource owner password credentials

·客户端模式:client credentials

注:本示例只演示密码模式和客户端模式,感兴趣的同学自己花时间测试另外两种授权模式。

获取token

密码模式

1、通过接口“/oauth/token”获取token信息,如下所示:

$ curl -d "username=user&password=123&grant_type=password&client_id=client&client_secret=secret&scope=app" http://198.9.9.21:8080/oauth/token

返回:

{"access_token":"8f9c7a5f-b0dd-48a3-a8d0-5969f172c15e","token_type":"bearer","refresh_token":"9fba821d-cbea-40c1-bb48-e173878eb6a1","expires_in":43088,"scope":"app"}

 

2、通过接口“/oauth/token”刷新token,如下所示:

$ curl -d "grant_type=refresh_token&client_id=client&client_secret=secret&refresh_token=9fba821d-cbea-40c1-bb48-e173878eb6a1" http://198.9.9.21:8080/oauth/token

返回:

{"access_token":"1092a1fe-5426-47bd-8091-bdff79039f30","token_type":"bearer","refresh_token":"9fba821d-cbea-40c1-bb48-e173878eb6a1","expires_in":43199,"scope":"app"}

 

客户端模式

1、通过接口“/oauth/token”获取token信息,如下所示:

$ curl -d "grant_type=client_credentials&client_id=client&client_secret=secret&scope=app" http://198.9.9.21:8080/oauth/token

返回:

{"access_token":"3e40b12a-ccdf-4c93-981b-8923a2d22358","token_type":"bearer","expires_in":43199,"scope":"app"}

校验token

密码模式

1、通过接口“/oauth/check_token”校验token信息,如下所示:

$ curl -d "token=1092a1fe-5426-47bd-8091-bdff79039f30" http://client:secret@198.9.9.21:8080/oauth/check_token

返回:

{"active":true,"exp":1510678642,"user_name":"user","authorities":["ROLE_USER","ROLE_API","ROLE_RESOURCE"],"client_id":"client","scope":["app"]}

客户端模式

curl -d "token=3e40b12a-ccdf-4c93-981b-8923a2d22358" http://client:secret@198.9.9.21:8080/oauth/check_token

返回:

{"scope":["app"],"active":true,"exp":1510678854,"client_id":"client"}

 

注:密码模式在校验token时会返回用户权限信息,客户端模式则没有权限信息返回,所以当用户权限信息归授权服务管辖时则采用密码模式,否则采用客户端授权模式。

构建资源服务

1、使用eclipse构建一个名称为“oauth2-resource”的maven项目,将其pom.xml配置文件修改为如下:

<project xmlns="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.0 http://maven.apache.org/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>oauth2-resource</groupId>

    <artifactId>oauth2-resource</artifactId>

    <packaging>war</packaging>

    <version>0.0.1-SNAPSHOT</version>

    <name>oauth2-resource Maven Webapp</name>

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

    <parent>

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

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

        <version>1.5.6.RELEASE</version>

    </parent>

    <dependencies>

        <dependency>

            <groupId>org.springframework.cloud</groupId>

            <artifactId>spring-cloud-security</artifactId>

            <version>1.2.1.RELEASE</version>

        </dependency>

        <dependency>

            <groupId>fort-spring-security-oauth2</groupId>

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

            <version>0.0.1-SNAPSHOT</version>

        </dependency>

        <dependency>

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

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

            <exclusions>

                <exclusion>

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

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

                </exclusion>

            </exclusions>

        </dependency>

        <!-- Log4j -->

        <dependency>

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

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

        </dependency>

    </dependencies>

    <build>

        <finalName>oauth2-resource</finalName>

    </build>

</project>

2、新建程序启动类“Application.java”,如下所示:

@SpringBootApplication

@EnableResourceServer

public class Application {



    public static void main(String[] args) {

        SpringApplication.run(Application.class, args);

    }



}

3、新建“AuthResourceConfig.java”类继承“ResourceServerConfigurerAdapter”类初始化资源服务所需要的信息,如下所示:

@Configuration

public class AuthResourceConfig extends ResourceServerConfigurerAdapter {



    @Override

    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {

        RemoteTokenServices tokenService = new RemoteTokenServices();

        tokenService.setClientId("client");

        tokenService.setClientSecret("secret");

        tokenService.setCheckTokenEndpointUrl("http://198.9.9.21:8080/oauth/check_token");

        resources.tokenServices(tokenService);

    }



    @Override

    public void configure(HttpSecurity http) throws Exception {

        http

            .authorizeRequests().antMatchers("/private/data").hasRole("RESOURCE")

            .antMatchers("/api/data").permitAll();

    }

}

4、新建“ResourceController.java”类构建资源服务所提供的接口,分别为 “/private/data”和“/api/data”,如下所示:

@RestController

public class ResourceController {

   

    @RequestMapping("/private/data")

    public String getResource() {

        Object details = SecurityContextHolder.getContext().getAuthentication().getDetails();

        OAuth2AuthenticationDetails oAuth2Authen = (OAuth2AuthenticationDetails) details;

        System.out.println(oAuth2Authen.getTokenType());

        System.out.println(SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString());

        return "Hello! This is private data.";

    }

   

    @RequestMapping("/api/data")

    public String getApiData() {

        Object details = SecurityContextHolder.getContext().getAuthentication().getDetails();

        if(details instanceof OAuth2AuthenticationDetails) {

            OAuth2AuthenticationDetails oAuth2Authen = (OAuth2AuthenticationDetails) details;

            System.out.println(oAuth2Authen.getTokenType());

            System.out.println(SecurityContextHolder.getContext().getAuthentication().getPrincipal().toString());

            return "Hello! This is api data.";

        }

        return "error";

    }

}

5、新建“application.yml”配置文件,内容如下:

server:
  port: 9001

启动资源服务

我们启动授权服务是通过运行“Application.java”来启动,同理也可以运行资源服务中的“Application.java”来启动资源服务。

资源服务接口权限测试

未授权访问接口

1、访问“/private/data”,如下所示:

$ curl http://198.9.9.21:9001/private/data

返回

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

2、访问“/api /data”,如下所示:

$ curl http://198.9.9.21:9001/api/data

返回

error

使用token访问接口

1、访问“/private/data”,如下所示:

·使用密码模式授权token访问

$ curl -d "usernaH "Authorization:Bearer 01a65ff5-cec7-4e2e-8812-69abac4ad566"  http://198.9.9.21:9001/private/data

返回

Hello! This is private data.

·使用客户端模式授权token访问

$ curl -H "Authorization:Bearer 3e40b12a-ccdf-4c93-981b-8923a2d22358"  http://198.9.9.21:9001/private/data

返回

{"error":"access_denied","error_description":"Access is denied"}

 

2、访问“/api /data”,如下所示:

$ curl -H "Authorization:Bearer 3e40b12a-ccdf-4c93-981b-8923a2d22358"  http://198.9.9.21:9001/api/data

返回

Hello! This is api data.

 

转载于:https://my.oschina.net/zhangzhigong/blog/1573379

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值