作者 钟来

初始提交

正在显示 45 个修改的文件 包含 1856 行增加0 行删除
  1 +### 简述:
  2 +- 允许内存、数据库、JWT等方式存储令牌
  3 +- 允许 JWT 方式验证令牌
  4 +- 允许从内存、数据库中读取客户端详情
  5 +- 封装配置类,简化配置,通过注解方式定制使用何种令牌存储方式、客户端详情获取方式,可使用 JWT 方式存储令牌,从数据库中获取客户端详情
  6 +- 提供完整单元测试
  7 +- 较为详细的代码注释
  8 +- ~~允许从授权服务器(适用于 JDBC、内存存储令牌)验证令牌~~ **该代码尚未完善,仅供参考**
  9 +- 数据库 Schema : https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/test/resources/schema.sql
  10 +- Demo Git 地址:https://gitee.com/LinYuanTongXue/OAuth2-Demo
  11 +
  12 +### Demo 流程:
  13 +- 使用 OAuth2 密码授权方式提供令牌
  14 +- 资源服务器1(也为客户端)提供登录接口,资源所有者(用户)通过将个人账号密码提供给 资源服务器1,资源服务器1 通过该信息向授权服务器获取令牌
  15 +- 资源服务器1(也为客户端)通过令牌(其中包含了客户端、用户等信息)访问自身受保护的资源(需要权限才能查看的资源)
  16 +- 资源服务器2(也可资源服务器)不包含登录接口,但其提供了某些受保护的资源(需要资源服务器1带着访问令牌才能访问)
  17 +- 资源服务器1(也为客户端)通过令牌向 资源服务器2(资源服务器) 请求其受保护的资源
  18 +
  19 +### 使用
  20 +- 授权服务器通过继承 **AuthServerConfig** 抽象类来配置授权服务器
  21 +- 资源服务器、客户端通过继承 **ResServerConfig** 抽象类来配置资源服务器
  22 +- Web 权限配置可继承 **AbstractSecurityConfig** 抽象类来简化配置
  23 +- 授权服务器通过在启动类添加以下注解来设置令牌存储、客户端信息获取方式
  24 + - **@EnableAuthJWTTokenStore**:使用 JWT 存储令牌
  25 + - **@EnableDBClientDetailsService**:通过数据库获取客户端详情
  26 + - **@EnableDBTokenStore**:通过数据库存储令牌
  27 +- 资源服务器通过在启动类添加以下注解来设置令牌解析方式
  28 + - **@EnableResJWTTokenStore**:使用 JWT 解析令牌
  29 + - ~~**@EnableRemoteTokenService**:通过授权服务器验证令牌~~ **该代码尚未完善,仅供参考**
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
  3 + <component name="FacetManager">
  4 + <facet type="Spring" name="Spring">
  5 + <configuration />
  6 + </facet>
  7 + </component>
  8 + <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
  9 + <output url="file://$MODULE_DIR$/target/classes" />
  10 + <output-test url="file://$MODULE_DIR$/target/test-classes" />
  11 + <content url="file://$MODULE_DIR$">
  12 + <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
  13 + <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
  14 + <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
  15 + <excludeFolder url="file://$MODULE_DIR$/target" />
  16 + </content>
  17 + <orderEntry type="inheritedJdk" />
  18 + <orderEntry type="sourceFolder" forTests="false" />
  19 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-starter-oauth2:1.2.2.RELEASE" level="project" />
  20 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-starter-security:1.2.2.RELEASE" level="project" />
  21 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-starter:1.3.1.RELEASE" level="project" />
  22 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-context:1.3.1.RELEASE" level="project" />
  23 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-crypto:4.2.3.RELEASE" level="project" />
  24 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-commons:1.3.1.RELEASE" level="project" />
  25 + <orderEntry type="library" name="Maven: org.apache.httpcomponents:httpclient:4.5.3" level="project" />
  26 + <orderEntry type="library" name="Maven: org.apache.httpcomponents:httpcore:4.4.8" level="project" />
  27 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-rsa:1.0.3.RELEASE" level="project" />
  28 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-actuator:1.5.9.RELEASE" level="project" />
  29 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-actuator:1.5.9.RELEASE" level="project" />
  30 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-security:1.2.2.RELEASE" level="project" />
  31 + <orderEntry type="library" name="Maven: org.springframework.security.oauth:spring-security-oauth2:2.0.14.RELEASE" level="project" />
  32 + <orderEntry type="library" name="Maven: org.springframework:spring-beans:4.3.13.RELEASE" level="project" />
  33 + <orderEntry type="library" name="Maven: org.springframework:spring-context:4.3.13.RELEASE" level="project" />
  34 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-core:4.2.3.RELEASE" level="project" />
  35 + <orderEntry type="library" name="Maven: aopalliance:aopalliance:1.0" level="project" />
  36 + <orderEntry type="library" name="Maven: commons-codec:commons-codec:1.10" level="project" />
  37 + <orderEntry type="library" name="Maven: org.codehaus.jackson:jackson-mapper-asl:1.9.13" level="project" />
  38 + <orderEntry type="library" name="Maven: org.codehaus.jackson:jackson-core-asl:1.9.13" level="project" />
  39 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-security:1.5.9.RELEASE" level="project" />
  40 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:1.5.9.RELEASE" level="project" />
  41 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-logging:1.5.9.RELEASE" level="project" />
  42 + <orderEntry type="library" name="Maven: ch.qos.logback:logback-classic:1.1.11" level="project" />
  43 + <orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.1.11" level="project" />
  44 + <orderEntry type="library" name="Maven: org.slf4j:jcl-over-slf4j:1.7.25" level="project" />
  45 + <orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.25" level="project" />
  46 + <orderEntry type="library" name="Maven: org.slf4j:log4j-over-slf4j:1.7.25" level="project" />
  47 + <orderEntry type="library" scope="RUNTIME" name="Maven: org.yaml:snakeyaml:1.17" level="project" />
  48 + <orderEntry type="library" name="Maven: org.springframework:spring-aop:4.3.13.RELEASE" level="project" />
  49 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-config:4.2.3.RELEASE" level="project" />
  50 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-web:4.2.3.RELEASE" level="project" />
  51 + <orderEntry type="library" name="Maven: org.springframework:spring-expression:4.3.13.RELEASE" level="project" />
  52 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-web:1.5.9.RELEASE" level="project" />
  53 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-tomcat:1.5.9.RELEASE" level="project" />
  54 + <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-core:8.5.23" level="project" />
  55 + <orderEntry type="library" name="Maven: org.apache.tomcat:tomcat-annotations-api:8.5.23" level="project" />
  56 + <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-el:8.5.23" level="project" />
  57 + <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-websocket:8.5.23" level="project" />
  58 + <orderEntry type="library" name="Maven: org.hibernate:hibernate-validator:5.3.6.Final" level="project" />
  59 + <orderEntry type="library" name="Maven: javax.validation:validation-api:1.1.0.Final" level="project" />
  60 + <orderEntry type="library" name="Maven: org.jboss.logging:jboss-logging:3.3.1.Final" level="project" />
  61 + <orderEntry type="library" name="Maven: com.fasterxml:classmate:1.3.4" level="project" />
  62 + <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.8.10" level="project" />
  63 + <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.8.0" level="project" />
  64 + <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.8.10" level="project" />
  65 + <orderEntry type="library" name="Maven: org.springframework:spring-web:4.3.13.RELEASE" level="project" />
  66 + <orderEntry type="library" name="Maven: org.springframework:spring-webmvc:4.3.13.RELEASE" level="project" />
  67 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-jwt:1.0.8.RELEASE" level="project" />
  68 + <orderEntry type="library" name="Maven: org.bouncycastle:bcpkix-jdk15on:1.56" level="project" />
  69 + <orderEntry type="library" name="Maven: org.bouncycastle:bcprov-jdk15on:1.56" level="project" />
  70 + <orderEntry type="module" module-name="oauth2-config" />
  71 + <orderEntry type="library" name="Maven: org.springframework.mobile:spring-mobile-device:1.1.5.RELEASE" level="project" />
  72 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-devtools:1.5.9.RELEASE" level="project" />
  73 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot:1.5.9.RELEASE" level="project" />
  74 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:1.5.9.RELEASE" level="project" />
  75 + <orderEntry type="library" scope="RUNTIME" name="Maven: com.h2database:h2:1.4.196" level="project" />
  76 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-jdbc:1.5.9.RELEASE" level="project" />
  77 + <orderEntry type="library" name="Maven: org.apache.tomcat:tomcat-jdbc:8.5.23" level="project" />
  78 + <orderEntry type="library" name="Maven: org.apache.tomcat:tomcat-juli:8.5.23" level="project" />
  79 + <orderEntry type="library" name="Maven: org.springframework:spring-jdbc:4.3.13.RELEASE" level="project" />
  80 + <orderEntry type="library" name="Maven: org.springframework:spring-tx:4.3.13.RELEASE" level="project" />
  81 + <orderEntry type="library" name="Maven: org.projectlombok:lombok:1.16.18" level="project" />
  82 + <orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-starter-test:1.5.9.RELEASE" level="project" />
  83 + <orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test:1.5.9.RELEASE" level="project" />
  84 + <orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test-autoconfigure:1.5.9.RELEASE" level="project" />
  85 + <orderEntry type="library" scope="TEST" name="Maven: com.jayway.jsonpath:json-path:2.2.0" level="project" />
  86 + <orderEntry type="library" scope="TEST" name="Maven: net.minidev:json-smart:2.2.1" level="project" />
  87 + <orderEntry type="library" scope="TEST" name="Maven: net.minidev:accessors-smart:1.1" level="project" />
  88 + <orderEntry type="library" scope="TEST" name="Maven: org.ow2.asm:asm:5.0.3" level="project" />
  89 + <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.25" level="project" />
  90 + <orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" />
  91 + <orderEntry type="library" scope="TEST" name="Maven: org.assertj:assertj-core:2.6.0" level="project" />
  92 + <orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-core:1.10.19" level="project" />
  93 + <orderEntry type="library" scope="TEST" name="Maven: org.objenesis:objenesis:2.1" level="project" />
  94 + <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
  95 + <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-library:1.3" level="project" />
  96 + <orderEntry type="library" scope="TEST" name="Maven: org.skyscreamer:jsonassert:1.4.0" level="project" />
  97 + <orderEntry type="library" scope="TEST" name="Maven: com.vaadin.external.google:android-json:0.0.20131108.vaadin1" level="project" />
  98 + <orderEntry type="library" name="Maven: org.springframework:spring-core:4.3.13.RELEASE" level="project" />
  99 + <orderEntry type="library" scope="TEST" name="Maven: org.springframework:spring-test:4.3.13.RELEASE" level="project" />
  100 + </component>
  101 +</module>
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4 + <parent>
  5 + <artifactId>oauth2-demo</artifactId>
  6 + <groupId>com.linyuan</groupId>
  7 + <version>0.0.1-SNAPSHOT</version>
  8 + <relativePath>../../oauth2-demo</relativePath>
  9 + </parent>
  10 + <modelVersion>4.0.0</modelVersion>
  11 +
  12 + <artifactId>authentication-server</artifactId>
  13 +</project>
  1 +package com.linyuan.authenticationserver;
  2 +
  3 +import com.linyuan.oauth2config.config.annotation.EnableAuthJWTTokenStore;
  4 +import org.springframework.boot.SpringApplication;
  5 +import org.springframework.boot.autoconfigure.SpringBootApplication;
  6 +
  7 +@SpringBootApplication
  8 +@EnableAuthJWTTokenStore // 使用 JWT 存储令牌
  9 +//@EnableDBClientDetailsService //从 JDBC 加载客户端详情,需配置在启动类上,若在子类上会出现顺序问题,导致 Bean 创建失败
  10 +public class AuthenticationServerApplication {
  11 +
  12 + public static void main(String[] args) {
  13 + SpringApplication.run(AuthenticationServerApplication.class, args);
  14 + }
  15 +}
  1 +package com.linyuan.authenticationserver.config;
  2 +
  3 +import com.linyuan.oauth2config.config.AuthServerConfig;
  4 +import org.springframework.context.annotation.Configuration;
  5 +import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
  6 +
  7 +import java.util.concurrent.TimeUnit;
  8 +
  9 +/**
  10 + * @author: 林塬
  11 + * @date: 2018/1/10
  12 + * @description: OAuth2 授权服务器配置
  13 + */
  14 +@Configuration
  15 +public class AuthorizationServerConfig extends AuthServerConfig {
  16 +
  17 + /**
  18 + * 调用父类构造函数,设置令牌失效日期等信息
  19 + */
  20 + public AuthorizationServerConfig() {
  21 + super((int)TimeUnit.DAYS.toSeconds(1), 0, false, false);
  22 + }
  23 +
  24 + /**
  25 + * 配置客户端详情
  26 + * @param clients
  27 + * @throws Exception
  28 + */
  29 + @Override
  30 + public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
  31 + super.configure(clients);
  32 + clients.inMemory() // 使用内存存储客户端信息
  33 + .withClient("resource1") // client_id
  34 + .secret("secret") // client_secret
  35 + .authorizedGrantTypes("authorization_code","password") // 该client允许的授权类型
  36 + .accessTokenValiditySeconds(3600) // Token 的有效期
  37 + .scopes("read") // 允许的授权范围
  38 + .autoApprove(true); //登录后绕过批准询问(/oauth/confirm_access)
  39 + }
  40 +}
  1 +package com.linyuan.authenticationserver.config;
  2 +
  3 +import com.linyuan.oauth2config.config.AbstractSecurityConfig;
  4 +import org.springframework.context.annotation.Configuration;
  5 +
  6 +/**
  7 + * @author: 林塬
  8 + * @date: 2018/1/19
  9 + * @description: 权限配置
  10 + */
  11 +@Configuration
  12 +public class WebSecurityConfig extends AbstractSecurityConfig {
  13 +
  14 +}
  1 +package com.linyuan.authenticationserver.service;
  2 +
  3 +import com.linyuan.oauth2config.constants.AuthoritiesEnum;
  4 +import org.springframework.security.core.authority.AuthorityUtils;
  5 +import org.springframework.security.core.userdetails.User;
  6 +import org.springframework.security.core.userdetails.UserDetails;
  7 +import org.springframework.security.core.userdetails.UsernameNotFoundException;
  8 +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  9 +import org.springframework.security.crypto.password.PasswordEncoder;
  10 +import org.springframework.stereotype.Service;
  11 +
  12 +/**
  13 + * @author: 林塬
  14 + * @date: 2018/1/9
  15 + * @description: 用户信息获取
  16 + */
  17 +@Service
  18 +public class UserDetailsService implements org.springframework.security.core.userdetails.UserDetailsService {
  19 +
  20 + /**
  21 + * 通过 Username 加载用户详情
  22 + * @param username 用户名
  23 + * @return UserDetails
  24 + * @throws UsernameNotFoundException
  25 + */
  26 + @Override
  27 + public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
  28 + if (username.equals("linyuan")) {
  29 + PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
  30 + String password = passwordEncoder.encode("123456");
  31 + UserDetails userDetails = new User("linyuan",
  32 + password,
  33 + AuthorityUtils.commaSeparatedStringToAuthorityList(AuthoritiesEnum.USER.getRole()));
  34 + return userDetails;
  35 + }
  36 + return null;
  37 + }
  38 +}
  1 +server:
  2 + port: 9005
  3 +encrypt:
  4 + key-store:
  5 + location: mytest.jks
  6 + secret: mypass
  7 + alias: mytest
  8 +# 若从数据库中获取客户端信息则需配置数据库源
  9 +#spring:
  10 +# datasource:
  11 +# driver-class-name: org.h2.Driver
  12 +# url: jdbc:h2:mem:test
  13 +# username: sa
  14 +# h2:
  15 +# console:
  16 +# enabled: true
  1 +package com.linyuan.authenticationserver.web.rest;
  2 +
  3 +import com.linyuan.authenticationserver.AuthenticationServerApplication;
  4 +import lombok.extern.slf4j.Slf4j;
  5 +import org.apache.http.HttpStatus;
  6 +import org.junit.Assert;
  7 +import org.junit.Test;
  8 +import org.junit.runner.RunWith;
  9 +import org.springframework.beans.factory.annotation.Autowired;
  10 +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
  11 +import org.springframework.boot.test.context.SpringBootTest;
  12 +import org.springframework.http.MediaType;
  13 +import org.springframework.test.context.junit4.SpringRunner;
  14 +import org.springframework.test.web.servlet.MockMvc;
  15 +import org.springframework.util.LinkedMultiValueMap;
  16 +import org.springframework.util.MultiValueMap;
  17 +
  18 +import java.util.Base64;
  19 +import java.util.Collections;
  20 +
  21 +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
  22 +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
  23 +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
  24 +
  25 +/**
  26 + * @author: 林塬
  27 + * @date: 2018/1/16
  28 + * @description: 令牌单元测试
  29 + */
  30 +@Slf4j
  31 +@RunWith(SpringRunner.class)
  32 +@SpringBootTest(classes = AuthenticationServerApplication.class)
  33 +@AutoConfigureMockMvc
  34 +public class TokenControllerTest {
  35 +
  36 + @Autowired
  37 + private MockMvc mockMvc;
  38 +
  39 + /**
  40 + * 密码授权模式获取令牌
  41 + *
  42 + * @throws Exception
  43 + */
  44 + @Test
  45 + public void getToken() throws Exception {
  46 + MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
  47 + map.put("username", Collections.singletonList("linyuan"));
  48 + map.put("password", Collections.singletonList("123456"));
  49 + map.put("grant_type", Collections.singletonList("password"));
  50 + map.put("scope", Collections.singletonList("read"));
  51 + int status = this.mockMvc.perform(
  52 + post("/oauth/token")
  53 + .header("Authorization", "Basic " + Base64.getEncoder().encodeToString("resource1:secret".getBytes()))
  54 + .params(map)
  55 + .contentType(MediaType.MULTIPART_FORM_DATA)
  56 + .accept(MediaType.APPLICATION_JSON)
  57 + ).andDo(print()).andReturn().getResponse().getStatus();
  58 + switch (status) {
  59 + case HttpStatus.SC_OK:
  60 + log.info("密码授权模式获取令牌---------------->成功(200)");
  61 + break;
  62 + case HttpStatus.SC_UNAUTHORIZED:
  63 + log.info("密码授权模式获取令牌---------------->失败(401---没有权限,请检查验证信息,账号是否存在、客户端信息)");
  64 + break;
  65 + case HttpStatus.SC_BAD_REQUEST:
  66 + log.info("密码授权模式获取令牌---------------->失败(400---请求失败,请检查密码是否正确)");
  67 + break;
  68 + default:
  69 + log.info("密码授权模式获取令牌---------------->失败({}---未知结果)",status);
  70 + break;
  71 + }
  72 + Assert.assertEquals(status,HttpStatus.SC_OK);
  73 + }
  74 +
  75 +}
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
  3 + <component name="FacetManager">
  4 + <facet type="Spring" name="Spring">
  5 + <configuration />
  6 + </facet>
  7 + </component>
  8 + <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
  9 + <output url="file://$MODULE_DIR$/target/classes" />
  10 + <output-test url="file://$MODULE_DIR$/target/test-classes" />
  11 + <content url="file://$MODULE_DIR$">
  12 + <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
  13 + <excludeFolder url="file://$MODULE_DIR$/target" />
  14 + </content>
  15 + <orderEntry type="inheritedJdk" />
  16 + <orderEntry type="sourceFolder" forTests="false" />
  17 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-starter-oauth2:1.2.2.RELEASE" level="project" />
  18 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-starter-security:1.2.2.RELEASE" level="project" />
  19 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-starter:1.3.1.RELEASE" level="project" />
  20 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-context:1.3.1.RELEASE" level="project" />
  21 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-crypto:4.2.3.RELEASE" level="project" />
  22 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-commons:1.3.1.RELEASE" level="project" />
  23 + <orderEntry type="library" name="Maven: org.apache.httpcomponents:httpclient:4.5.3" level="project" />
  24 + <orderEntry type="library" name="Maven: org.apache.httpcomponents:httpcore:4.4.8" level="project" />
  25 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-rsa:1.0.3.RELEASE" level="project" />
  26 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-actuator:1.5.9.RELEASE" level="project" />
  27 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-actuator:1.5.9.RELEASE" level="project" />
  28 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-security:1.2.2.RELEASE" level="project" />
  29 + <orderEntry type="library" name="Maven: org.springframework.security.oauth:spring-security-oauth2:2.0.14.RELEASE" level="project" />
  30 + <orderEntry type="library" name="Maven: org.springframework:spring-beans:4.3.13.RELEASE" level="project" />
  31 + <orderEntry type="library" name="Maven: org.springframework:spring-context:4.3.13.RELEASE" level="project" />
  32 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-core:4.2.3.RELEASE" level="project" />
  33 + <orderEntry type="library" name="Maven: aopalliance:aopalliance:1.0" level="project" />
  34 + <orderEntry type="library" name="Maven: commons-codec:commons-codec:1.10" level="project" />
  35 + <orderEntry type="library" name="Maven: org.codehaus.jackson:jackson-mapper-asl:1.9.13" level="project" />
  36 + <orderEntry type="library" name="Maven: org.codehaus.jackson:jackson-core-asl:1.9.13" level="project" />
  37 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-security:1.5.9.RELEASE" level="project" />
  38 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:1.5.9.RELEASE" level="project" />
  39 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-logging:1.5.9.RELEASE" level="project" />
  40 + <orderEntry type="library" name="Maven: ch.qos.logback:logback-classic:1.1.11" level="project" />
  41 + <orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.1.11" level="project" />
  42 + <orderEntry type="library" name="Maven: org.slf4j:jcl-over-slf4j:1.7.25" level="project" />
  43 + <orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.25" level="project" />
  44 + <orderEntry type="library" name="Maven: org.slf4j:log4j-over-slf4j:1.7.25" level="project" />
  45 + <orderEntry type="library" scope="RUNTIME" name="Maven: org.yaml:snakeyaml:1.17" level="project" />
  46 + <orderEntry type="library" name="Maven: org.springframework:spring-aop:4.3.13.RELEASE" level="project" />
  47 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-config:4.2.3.RELEASE" level="project" />
  48 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-web:4.2.3.RELEASE" level="project" />
  49 + <orderEntry type="library" name="Maven: org.springframework:spring-expression:4.3.13.RELEASE" level="project" />
  50 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-web:1.5.9.RELEASE" level="project" />
  51 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-tomcat:1.5.9.RELEASE" level="project" />
  52 + <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-core:8.5.23" level="project" />
  53 + <orderEntry type="library" name="Maven: org.apache.tomcat:tomcat-annotations-api:8.5.23" level="project" />
  54 + <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-el:8.5.23" level="project" />
  55 + <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-websocket:8.5.23" level="project" />
  56 + <orderEntry type="library" name="Maven: org.hibernate:hibernate-validator:5.3.6.Final" level="project" />
  57 + <orderEntry type="library" name="Maven: javax.validation:validation-api:1.1.0.Final" level="project" />
  58 + <orderEntry type="library" name="Maven: org.jboss.logging:jboss-logging:3.3.1.Final" level="project" />
  59 + <orderEntry type="library" name="Maven: com.fasterxml:classmate:1.3.4" level="project" />
  60 + <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.8.10" level="project" />
  61 + <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.8.0" level="project" />
  62 + <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.8.10" level="project" />
  63 + <orderEntry type="library" name="Maven: org.springframework:spring-web:4.3.13.RELEASE" level="project" />
  64 + <orderEntry type="library" name="Maven: org.springframework:spring-webmvc:4.3.13.RELEASE" level="project" />
  65 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-jwt:1.0.8.RELEASE" level="project" />
  66 + <orderEntry type="library" name="Maven: org.bouncycastle:bcpkix-jdk15on:1.56" level="project" />
  67 + <orderEntry type="library" name="Maven: org.bouncycastle:bcprov-jdk15on:1.56" level="project" />
  68 + <orderEntry type="library" name="Maven: org.springframework.mobile:spring-mobile-device:1.1.5.RELEASE" level="project" />
  69 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-devtools:1.5.9.RELEASE" level="project" />
  70 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot:1.5.9.RELEASE" level="project" />
  71 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:1.5.9.RELEASE" level="project" />
  72 + <orderEntry type="library" scope="RUNTIME" name="Maven: com.h2database:h2:1.4.196" level="project" />
  73 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-jdbc:1.5.9.RELEASE" level="project" />
  74 + <orderEntry type="library" name="Maven: org.apache.tomcat:tomcat-jdbc:8.5.23" level="project" />
  75 + <orderEntry type="library" name="Maven: org.apache.tomcat:tomcat-juli:8.5.23" level="project" />
  76 + <orderEntry type="library" name="Maven: org.springframework:spring-jdbc:4.3.13.RELEASE" level="project" />
  77 + <orderEntry type="library" name="Maven: org.springframework:spring-tx:4.3.13.RELEASE" level="project" />
  78 + <orderEntry type="library" name="Maven: org.projectlombok:lombok:1.16.18" level="project" />
  79 + <orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-starter-test:1.5.9.RELEASE" level="project" />
  80 + <orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test:1.5.9.RELEASE" level="project" />
  81 + <orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test-autoconfigure:1.5.9.RELEASE" level="project" />
  82 + <orderEntry type="library" scope="TEST" name="Maven: com.jayway.jsonpath:json-path:2.2.0" level="project" />
  83 + <orderEntry type="library" scope="TEST" name="Maven: net.minidev:json-smart:2.2.1" level="project" />
  84 + <orderEntry type="library" scope="TEST" name="Maven: net.minidev:accessors-smart:1.1" level="project" />
  85 + <orderEntry type="library" scope="TEST" name="Maven: org.ow2.asm:asm:5.0.3" level="project" />
  86 + <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.25" level="project" />
  87 + <orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" />
  88 + <orderEntry type="library" scope="TEST" name="Maven: org.assertj:assertj-core:2.6.0" level="project" />
  89 + <orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-core:1.10.19" level="project" />
  90 + <orderEntry type="library" scope="TEST" name="Maven: org.objenesis:objenesis:2.1" level="project" />
  91 + <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
  92 + <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-library:1.3" level="project" />
  93 + <orderEntry type="library" scope="TEST" name="Maven: org.skyscreamer:jsonassert:1.4.0" level="project" />
  94 + <orderEntry type="library" scope="TEST" name="Maven: com.vaadin.external.google:android-json:0.0.20131108.vaadin1" level="project" />
  95 + <orderEntry type="library" name="Maven: org.springframework:spring-core:4.3.13.RELEASE" level="project" />
  96 + <orderEntry type="library" scope="TEST" name="Maven: org.springframework:spring-test:4.3.13.RELEASE" level="project" />
  97 + </component>
  98 +</module>
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4 + <parent>
  5 + <artifactId>oauth2-demo</artifactId>
  6 + <groupId>com.linyuan</groupId>
  7 + <version>0.0.1-SNAPSHOT</version>
  8 + <relativePath>../../oauth2-demo</relativePath>
  9 + </parent>
  10 + <modelVersion>4.0.0</modelVersion>
  11 +
  12 + <artifactId>oauth2-config</artifactId>
  13 +
  14 +</project>
  1 +package com.linyuan.oauth2config.config;
  2 +
  3 +import com.linyuan.oauth2config.constants.AuthoritiesEnum;
  4 +import lombok.AllArgsConstructor;
  5 +import org.springframework.beans.factory.BeanInitializationException;
  6 +import org.springframework.beans.factory.annotation.Autowired;
  7 +import org.springframework.context.annotation.Bean;
  8 +import org.springframework.context.annotation.Configuration;
  9 +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
  10 +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
  11 +import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  12 +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
  13 +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
  14 +import org.springframework.security.config.http.SessionCreationPolicy;
  15 +import org.springframework.security.core.userdetails.UserDetailsService;
  16 +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  17 +import org.springframework.security.crypto.password.PasswordEncoder;
  18 +
  19 +import javax.annotation.PostConstruct;
  20 +
  21 +/**
  22 + * @author: 林塬
  23 + * @date: 2018/1/20
  24 + * @description: Web 权限配置类
  25 + */
  26 +@Configuration
  27 +@EnableWebSecurity
  28 +@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
  29 +public abstract class AbstractSecurityConfig extends WebSecurityConfigurerAdapter {
  30 +
  31 + @Autowired
  32 + private AuthenticationManagerBuilder authenticationManagerBuilder;
  33 +
  34 + @Autowired
  35 + private UserDetailsService userDetailsService;
  36 +
  37 + @PostConstruct
  38 + public void init() {
  39 + try {
  40 + authenticationManagerBuilder
  41 + .userDetailsService(userDetailsService)
  42 + .passwordEncoder(passwordEncoder());
  43 + } catch (Exception e) {
  44 + throw new BeanInitializationException("Security configuration failed", e);
  45 + }
  46 + }
  47 +
  48 + @Bean
  49 + public PasswordEncoder passwordEncoder() {
  50 + return new BCryptPasswordEncoder();
  51 + }
  52 +
  53 + @Override
  54 + protected void configure(HttpSecurity http) throws Exception {
  55 + http
  56 + .exceptionHandling()
  57 + .and()
  58 + .csrf()
  59 + .disable()
  60 + .headers()
  61 + .frameOptions()
  62 + .disable()
  63 + .and()
  64 + .sessionManagement()
  65 + .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
  66 + .and()
  67 + .authorizeRequests()
  68 + .antMatchers("/swagger-ui/index.html").hasAuthority(AuthoritiesEnum.ADMIN.getRole());
  69 + }
  70 +
  71 +}
  1 +package com.linyuan.oauth2config.config;
  2 +
  3 +import org.springframework.beans.factory.annotation.Autowired;
  4 +import org.springframework.context.ApplicationContext;
  5 +import org.springframework.context.annotation.Configuration;
  6 +import org.springframework.context.annotation.Import;
  7 +import org.springframework.security.authentication.AuthenticationManager;
  8 +import org.springframework.security.core.userdetails.UserDetailsService;
  9 +import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
  10 +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
  11 +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
  12 +import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
  13 +import org.springframework.security.oauth2.provider.ClientDetailsService;
  14 +import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
  15 +import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
  16 +import org.springframework.security.oauth2.provider.token.TokenEnhancer;
  17 +import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
  18 +import org.springframework.security.oauth2.provider.token.TokenStore;
  19 +
  20 +import java.util.ArrayList;
  21 +import java.util.Collection;
  22 +import java.util.Objects;
  23 +
  24 +/**
  25 + * @author: 林塬
  26 + * @date: 2018/1/20
  27 + * @description: OAuth2 授权服务器配置类
  28 + */
  29 +@EnableAuthorizationServer
  30 +public abstract class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
  31 +
  32 + @Autowired
  33 + private ApplicationContext applicationContext;
  34 +
  35 + @Autowired
  36 + private TokenStore tokenStore;
  37 +
  38 + @Autowired
  39 + private AuthenticationManager authenticationManager;
  40 +
  41 + @Autowired
  42 + private UserDetailsService userDetailsService;
  43 +
  44 + @Autowired(required = false)
  45 + private JdbcClientDetailsService jdbcClientDetailsService;
  46 +
  47 + //令牌失效时间
  48 + public int accessTokenValiditySeconds;
  49 +
  50 + //刷新令牌失效时间
  51 + public int refreshTokenValiditySeconds;
  52 +
  53 + //是否可以重用刷新令牌
  54 + public boolean isReuseRefreshToken;
  55 +
  56 + //是否支持刷新令牌
  57 + public boolean isSupportRefreshToken;
  58 +
  59 +
  60 + public AuthServerConfig(int accessTokenValiditySeconds, int refreshTokenValiditySeconds, boolean isReuseRefreshToken, boolean isSupportRefreshToken) {
  61 + this.accessTokenValiditySeconds = accessTokenValiditySeconds;
  62 + this.refreshTokenValiditySeconds = refreshTokenValiditySeconds;
  63 + this.isReuseRefreshToken = isReuseRefreshToken;
  64 + this.isSupportRefreshToken = isSupportRefreshToken;
  65 + }
  66 +
  67 + /**
  68 + * 配置授权服务器端点,如令牌存储,令牌自定义,用户批准和授权类型,不包括端点安全配置
  69 + * @param endpoints
  70 + * @throws Exception
  71 + */
  72 + @Override
  73 + public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
  74 + Collection<TokenEnhancer> tokenEnhancers = applicationContext.getBeansOfType(TokenEnhancer.class).values();
  75 + TokenEnhancerChain tokenEnhancerChain=new TokenEnhancerChain();
  76 + tokenEnhancerChain.setTokenEnhancers(new ArrayList<>(tokenEnhancers));
  77 +
  78 + DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
  79 + defaultTokenServices.setReuseRefreshToken(isReuseRefreshToken);
  80 + defaultTokenServices.setSupportRefreshToken(isSupportRefreshToken);
  81 + defaultTokenServices.setTokenStore(tokenStore);
  82 + defaultTokenServices.setAccessTokenValiditySeconds(accessTokenValiditySeconds);
  83 + defaultTokenServices.setRefreshTokenValiditySeconds(refreshTokenValiditySeconds);
  84 + defaultTokenServices.setTokenEnhancer(tokenEnhancerChain);
  85 + //若通过 JDBC 存储令牌
  86 + if (Objects.nonNull(jdbcClientDetailsService)){
  87 + defaultTokenServices.setClientDetailsService(jdbcClientDetailsService);
  88 + }
  89 +
  90 + endpoints
  91 + .authenticationManager(authenticationManager)
  92 + .userDetailsService(userDetailsService)
  93 + .tokenServices(defaultTokenServices);
  94 + }
  95 +
  96 +
  97 + /**
  98 + * 配置授权服务器端点的安全
  99 + * @param oauthServer
  100 + * @throws Exception
  101 + */
  102 + @Override
  103 + public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
  104 + oauthServer
  105 + .tokenKeyAccess("permitAll()")
  106 + .checkTokenAccess("permitAll()")
  107 + .allowFormAuthenticationForClients();
  108 + }
  109 +
  110 +}
  1 +package com.linyuan.oauth2config.config;
  2 +
  3 +import org.springframework.beans.factory.annotation.Autowired;
  4 +import org.springframework.beans.factory.annotation.Qualifier;
  5 +import org.springframework.boot.autoconfigure.security.oauth2.OAuth2ClientProperties;
  6 +import org.springframework.context.annotation.Bean;
  7 +import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
  8 +import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  9 +import org.springframework.security.config.http.SessionCreationPolicy;
  10 +import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
  11 +import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
  12 +import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
  13 +import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
  14 +import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher;
  15 +import org.springframework.security.web.util.matcher.RequestMatcher;
  16 +import org.springframework.util.StringUtils;
  17 +
  18 +import java.util.Objects;
  19 +
  20 +/**
  21 + * @author: 林塬
  22 + * @date: 2018/1/20
  23 + * @description: OAuth2 资源服务器配置类
  24 + */
  25 +@EnableResourceServer
  26 +@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
  27 +public abstract class ResServerConfig extends ResourceServerConfigurerAdapter {
  28 +
  29 + @Autowired(required = false)
  30 + private RemoteTokenServices remoteTokenServices;
  31 +
  32 + @Autowired
  33 + private OAuth2ClientProperties oAuth2ClientProperties;
  34 +
  35 + @Bean
  36 + @Qualifier("authorizationHeaderRequestMatcher")
  37 + public RequestMatcher authorizationHeaderRequestMatcher() {
  38 + return new RequestHeaderRequestMatcher("Authorization");
  39 + }
  40 +
  41 + @Override
  42 + public void configure(HttpSecurity http) throws Exception {
  43 + http
  44 + .csrf()
  45 + .disable()
  46 + .exceptionHandling()
  47 + .and()
  48 + .headers()
  49 + .frameOptions()
  50 + .disable()
  51 + .and()
  52 + .sessionManagement()
  53 + .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
  54 + .and()
  55 + .requestMatcher(authorizationHeaderRequestMatcher());
  56 + }
  57 +
  58 + @Override
  59 + public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
  60 + super.configure(resources);
  61 + if (StringUtils.isEmpty(oAuth2ClientProperties.getClientId())) {
  62 + resources.resourceId(oAuth2ClientProperties.getClientId());
  63 + }
  64 + if (Objects.nonNull(remoteTokenServices)) {
  65 + resources.tokenServices(remoteTokenServices);
  66 + }
  67 + }
  68 +}
  1 +package com.linyuan.oauth2config.config.annotation;
  2 +
  3 +import com.linyuan.oauth2config.config.store.AuthJWTTokenStore;
  4 +import org.springframework.context.annotation.Import;
  5 +
  6 +import java.lang.annotation.ElementType;
  7 +import java.lang.annotation.Retention;
  8 +import java.lang.annotation.RetentionPolicy;
  9 +import java.lang.annotation.Target;
  10 +
  11 +/**
  12 + * @author: 林塬
  13 + * @date: 2018/1/22
  14 + * @description: 在启动类上添加该注解来----开启 JWT 令牌存储(授权服务器-非对称加密)
  15 + */
  16 +@Target(ElementType.TYPE)
  17 +@Retention(RetentionPolicy.RUNTIME)
  18 +@Import(AuthJWTTokenStore.class)
  19 +public @interface EnableAuthJWTTokenStore {
  20 +}
  1 +package com.linyuan.oauth2config.config.annotation;
  2 +
  3 +import com.linyuan.oauth2config.config.service.DBClientDetailsService;
  4 +import org.springframework.context.annotation.Import;
  5 +
  6 +import java.lang.annotation.ElementType;
  7 +import java.lang.annotation.Retention;
  8 +import java.lang.annotation.RetentionPolicy;
  9 +import java.lang.annotation.Target;
  10 +
  11 +/**
  12 + * @author: 林塬
  13 + * @date: 2018/1/22
  14 + * @description: 在启动类上添加该注解来----开启从数据库加载客户端详情
  15 + */
  16 +@Target(ElementType.TYPE)
  17 +@Retention(RetentionPolicy.RUNTIME)
  18 +@Import(DBClientDetailsService.class)
  19 +public @interface EnableDBClientDetailsService {
  20 +}
  1 +package com.linyuan.oauth2config.config.annotation;
  2 +
  3 +import com.linyuan.oauth2config.config.store.DBTokenStore;
  4 +import org.springframework.context.annotation.Import;
  5 +
  6 +import java.lang.annotation.ElementType;
  7 +import java.lang.annotation.Retention;
  8 +import java.lang.annotation.RetentionPolicy;
  9 +import java.lang.annotation.Target;
  10 +
  11 +/**
  12 + * @author: 林塬
  13 + * @date: 2018/1/22
  14 + * @description: 在启动类上添加该注解来----开启通过数据库存储令牌
  15 + * 数据库 schema :https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/test/resources/schema.sql
  16 + */
  17 +@Target(ElementType.TYPE)
  18 +@Retention(RetentionPolicy.RUNTIME)
  19 +@Import(DBTokenStore.class)
  20 +public @interface EnableDBTokenStore {
  21 +}
  1 +package com.linyuan.oauth2config.config.annotation;
  2 +
  3 +import com.linyuan.oauth2config.config.service.RemoteTokenService;
  4 +import org.springframework.context.annotation.Import;
  5 +
  6 +import java.lang.annotation.ElementType;
  7 +import java.lang.annotation.Retention;
  8 +import java.lang.annotation.RetentionPolicy;
  9 +import java.lang.annotation.Target;
  10 +
  11 +/**
  12 + * @author: 林塬
  13 + * @date: 2018/1/22
  14 + * @description: 在启动类上添加该注解来----开启通过授权服务器验证访问令牌(适用于 JDBC、内存存储令牌)
  15 + */
  16 +@Target(ElementType.TYPE)
  17 +@Retention(RetentionPolicy.RUNTIME)
  18 +@Import(RemoteTokenService.class)
  19 +public @interface EnableRemoteTokenService {
  20 +}
  1 +package com.linyuan.oauth2config.config.annotation;
  2 +
  3 +import com.linyuan.oauth2config.config.store.ResJWTTokenStore;
  4 +import org.springframework.context.annotation.Import;
  5 +
  6 +import java.lang.annotation.ElementType;
  7 +import java.lang.annotation.Retention;
  8 +import java.lang.annotation.RetentionPolicy;
  9 +import java.lang.annotation.Target;
  10 +
  11 +/**
  12 + * @author: 林塬
  13 + * @date: 2018/1/22
  14 + * @description: 在启动类上添加该注解来----开启 JWT 令牌存储(资源服务器-非对称加密)
  15 + */
  16 +@Target(ElementType.TYPE)
  17 +@Retention(RetentionPolicy.RUNTIME)
  18 +@Import(ResJWTTokenStore.class)
  19 +public @interface EnableResJWTTokenStore {
  20 +}
  1 +package com.linyuan.oauth2config.config.service;
  2 +
  3 +import org.springframework.beans.factory.annotation.Autowired;
  4 +import org.springframework.context.annotation.Bean;
  5 +import org.springframework.security.oauth2.provider.ClientDetailsService;
  6 +import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
  7 +
  8 +import javax.sql.DataSource;
  9 +
  10 +/**
  11 + * @author: 林塬
  12 + * @date: 2018/1/22
  13 + * @description: 通过数据库加载客户端详情
  14 + */
  15 +public class DBClientDetailsService {
  16 +
  17 + @Autowired
  18 + private DataSource dataSource;
  19 +
  20 + @Bean
  21 + public ClientDetailsService clientDetailsService(){
  22 + return new JdbcClientDetailsService(dataSource);
  23 + }
  24 +
  25 +}
  1 +package com.linyuan.oauth2config.config.service;
  2 +
  3 +import org.springframework.beans.factory.annotation.Autowired;
  4 +import org.springframework.boot.autoconfigure.security.oauth2.OAuth2ClientProperties;
  5 +import org.springframework.boot.autoconfigure.security.oauth2.authserver.AuthorizationServerProperties;
  6 +import org.springframework.context.annotation.Bean;
  7 +import org.springframework.security.oauth2.provider.token.AccessTokenConverter;
  8 +import org.springframework.security.oauth2.provider.token.DefaultAccessTokenConverter;
  9 +import org.springframework.security.oauth2.provider.token.RemoteTokenServices;
  10 +import org.springframework.security.oauth2.provider.token.ResourceServerTokenServices;
  11 +import org.springframework.util.StringUtils;
  12 +
  13 +import javax.annotation.Resource;
  14 +
  15 +/**
  16 + * @author: 林塬
  17 + * @date: 2018/1/22
  18 + * @description: 通过访问远程授权服务器 check_token 端点验证令牌
  19 + */
  20 +public class RemoteTokenService {
  21 +
  22 + @Autowired
  23 + private OAuth2ClientProperties oAuth2ClientProperties;
  24 +
  25 + @Resource(name = "authServerProp")
  26 + private AuthorizationServerProperties authorizationServerProperties;
  27 +
  28 + @Bean(name = "authServerProp")
  29 + public AuthorizationServerProperties authorizationServerProperties(){
  30 + return new AuthorizationServerProperties();
  31 + }
  32 +
  33 + @Bean
  34 + public ResourceServerTokenServices tokenServices() {
  35 + RemoteTokenServices remoteTokenServices = new RemoteTokenServices();
  36 + remoteTokenServices.setCheckTokenEndpointUrl(authorizationServerProperties.getCheckTokenAccess());
  37 + if (StringUtils.isEmpty(oAuth2ClientProperties.getClientId())) {
  38 + remoteTokenServices.setClientId(oAuth2ClientProperties.getClientId());
  39 + }
  40 + if (StringUtils.isEmpty(oAuth2ClientProperties.getClientSecret())){
  41 + remoteTokenServices.setClientSecret(oAuth2ClientProperties.getClientSecret());
  42 + }
  43 + remoteTokenServices.setAccessTokenConverter(accessTokenConverter());
  44 + return remoteTokenServices;
  45 + }
  46 +
  47 + @Bean
  48 + public AccessTokenConverter accessTokenConverter() {
  49 + return new DefaultAccessTokenConverter();
  50 + }
  51 +
  52 +}
  1 +package com.linyuan.oauth2config.config.store;
  2 +
  3 +import org.springframework.cloud.bootstrap.encrypt.KeyProperties;
  4 +import org.springframework.context.annotation.Bean;
  5 +import org.springframework.security.oauth2.provider.token.TokenStore;
  6 +import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
  7 +import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
  8 +import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
  9 +
  10 +import javax.annotation.Resource;
  11 +import java.security.KeyPair;
  12 +
  13 +/**
  14 + * @author: 林塬
  15 + * @date: 2018/1/20
  16 + * @description: 授权服务器 TokenStore 配置类,使用 JWT RSA 非对称加密
  17 + */
  18 +public class AuthJWTTokenStore {
  19 +
  20 + @Bean("keyProp")
  21 + public KeyProperties keyProperties(){
  22 + return new KeyProperties();
  23 + }
  24 +
  25 + @Resource(name = "keyProp")
  26 + private KeyProperties keyProperties;
  27 +
  28 + @Bean
  29 + public TokenStore tokenStore(JwtAccessTokenConverter jwtAccessTokenConverter) {
  30 + return new JwtTokenStore(jwtAccessTokenConverter);
  31 + }
  32 +
  33 + @Bean
  34 + public JwtAccessTokenConverter jwtAccessTokenConverter() {
  35 + JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
  36 + KeyPair keyPair = new KeyStoreKeyFactory
  37 + (keyProperties.getKeyStore().getLocation(), keyProperties.getKeyStore().getSecret().toCharArray())
  38 + .getKeyPair(keyProperties.getKeyStore().getAlias());
  39 + converter.setKeyPair(keyPair);
  40 + return converter;
  41 + }
  42 +
  43 +}
  1 +package com.linyuan.oauth2config.config.store;
  2 +
  3 +import org.springframework.beans.factory.annotation.Autowired;
  4 +import org.springframework.context.annotation.Bean;
  5 +import org.springframework.security.oauth2.provider.token.TokenStore;
  6 +import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
  7 +
  8 +import javax.sql.DataSource;
  9 +
  10 +/**
  11 + * @author: 林塬
  12 + * @date: 2018/1/22
  13 + * @description: 使用数据库存取令牌
  14 + */
  15 +public class DBTokenStore {
  16 +
  17 + @Autowired
  18 + private DataSource dataSource;
  19 +
  20 + @Bean
  21 + public TokenStore tokenStore(){
  22 + return new JdbcTokenStore(dataSource);
  23 + }
  24 +
  25 +}
  1 +package com.linyuan.oauth2config.config.store;
  2 +
  3 +import com.fasterxml.jackson.databind.ObjectMapper;
  4 +import org.springframework.beans.factory.annotation.Autowired;
  5 +import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties;
  6 +import org.springframework.context.annotation.Bean;
  7 +import org.springframework.core.io.ClassPathResource;
  8 +import org.springframework.core.io.Resource;
  9 +import org.springframework.security.oauth2.provider.token.TokenStore;
  10 +import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
  11 +import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
  12 +import org.springframework.web.client.RestTemplate;
  13 +
  14 +import java.io.BufferedReader;
  15 +import java.io.IOException;
  16 +import java.io.InputStreamReader;
  17 +import java.util.Map;
  18 +import java.util.stream.Collectors;
  19 +
  20 +/**
  21 + * @author: 林塬
  22 + * @date: 2018/1/20
  23 + * @description: 资源服务器 TokenStore 配置类,使用 JWT RSA 非对称加密
  24 + */
  25 +public class ResJWTTokenStore {
  26 +
  27 + private static final String PUBLIC_KEY = "pubkey.txt";
  28 +
  29 + @Autowired
  30 + private ResourceServerProperties resourceServerProperties;
  31 +
  32 + @Bean
  33 + public TokenStore tokenStore(JwtAccessTokenConverter jwtAccessTokenConverter) {
  34 + return new JwtTokenStore(jwtAccessTokenConverter);
  35 + }
  36 +
  37 + @Bean
  38 + public JwtAccessTokenConverter jwtAccessTokenConverter() {
  39 + JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
  40 + converter.setVerifierKey(getPubKey());
  41 + return converter;
  42 + }
  43 +
  44 + /**
  45 + * 获取非对称加密公钥 Key
  46 + * @return 公钥 Key
  47 + */
  48 + private String getPubKey() {
  49 + Resource resource = new ClassPathResource(ResJWTTokenStore.PUBLIC_KEY);
  50 + try (BufferedReader br = new BufferedReader(new InputStreamReader(resource.getInputStream()))) {
  51 + return br.lines().collect(Collectors.joining("\n"));
  52 + } catch (IOException ioe) {
  53 + return getKeyFromAuthorizationServer();
  54 + }
  55 + }
  56 +
  57 + /**
  58 + * 通过访问授权服务器获取非对称加密公钥 Key
  59 + * @return 公钥 Key
  60 + */
  61 + private String getKeyFromAuthorizationServer() {
  62 + ObjectMapper objectMapper = new ObjectMapper();
  63 + String pubKey = new RestTemplate().getForObject(resourceServerProperties.getJwt().getKeyUri(), String.class);
  64 + try {
  65 + Map map = objectMapper.readValue(pubKey, Map.class);
  66 + return map.get("value").toString();
  67 + } catch (IOException e) {
  68 + e.printStackTrace();
  69 + }
  70 + return null;
  71 + }
  72 +
  73 +}
  1 +package com.linyuan.oauth2config.constants;
  2 +
  3 +/**
  4 + * @author: 林塬
  5 + * @date: 2018/1/20
  6 + * @description: 权限常量
  7 + */
  8 +public enum AuthoritiesEnum {
  9 + ADMIN("ROLE_ADMIN"),
  10 + USER("ROLE_USER"),
  11 + ANONYMOUS("ROLE_ANONYMOUS");
  12 +
  13 + private String role;
  14 +
  15 + AuthoritiesEnum(String role) {
  16 + this.role = role;
  17 + }
  18 +
  19 + public String getRole() {
  20 + return role;
  21 + }
  22 +
  23 +}
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
  3 + <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
  4 + <output url="file://$MODULE_DIR$/target/classes" />
  5 + <output-test url="file://$MODULE_DIR$/target/test-classes" />
  6 + <content url="file://$MODULE_DIR$">
  7 + <excludeFolder url="file://$MODULE_DIR$/target" />
  8 + </content>
  9 + <orderEntry type="inheritedJdk" />
  10 + <orderEntry type="sourceFolder" forTests="false" />
  11 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-starter-oauth2:1.2.2.RELEASE" level="project" />
  12 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-starter-security:1.2.2.RELEASE" level="project" />
  13 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-starter:1.3.1.RELEASE" level="project" />
  14 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-context:1.3.1.RELEASE" level="project" />
  15 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-crypto:4.2.3.RELEASE" level="project" />
  16 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-commons:1.3.1.RELEASE" level="project" />
  17 + <orderEntry type="library" name="Maven: org.apache.httpcomponents:httpclient:4.5.3" level="project" />
  18 + <orderEntry type="library" name="Maven: org.apache.httpcomponents:httpcore:4.4.8" level="project" />
  19 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-rsa:1.0.3.RELEASE" level="project" />
  20 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-actuator:1.5.9.RELEASE" level="project" />
  21 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-actuator:1.5.9.RELEASE" level="project" />
  22 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-security:1.2.2.RELEASE" level="project" />
  23 + <orderEntry type="library" name="Maven: org.springframework.security.oauth:spring-security-oauth2:2.0.14.RELEASE" level="project" />
  24 + <orderEntry type="library" name="Maven: org.springframework:spring-beans:4.3.13.RELEASE" level="project" />
  25 + <orderEntry type="library" name="Maven: org.springframework:spring-context:4.3.13.RELEASE" level="project" />
  26 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-core:4.2.3.RELEASE" level="project" />
  27 + <orderEntry type="library" name="Maven: aopalliance:aopalliance:1.0" level="project" />
  28 + <orderEntry type="library" name="Maven: commons-codec:commons-codec:1.10" level="project" />
  29 + <orderEntry type="library" name="Maven: org.codehaus.jackson:jackson-mapper-asl:1.9.13" level="project" />
  30 + <orderEntry type="library" name="Maven: org.codehaus.jackson:jackson-core-asl:1.9.13" level="project" />
  31 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-security:1.5.9.RELEASE" level="project" />
  32 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:1.5.9.RELEASE" level="project" />
  33 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-logging:1.5.9.RELEASE" level="project" />
  34 + <orderEntry type="library" name="Maven: ch.qos.logback:logback-classic:1.1.11" level="project" />
  35 + <orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.1.11" level="project" />
  36 + <orderEntry type="library" name="Maven: org.slf4j:jcl-over-slf4j:1.7.25" level="project" />
  37 + <orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.25" level="project" />
  38 + <orderEntry type="library" name="Maven: org.slf4j:log4j-over-slf4j:1.7.25" level="project" />
  39 + <orderEntry type="library" scope="RUNTIME" name="Maven: org.yaml:snakeyaml:1.17" level="project" />
  40 + <orderEntry type="library" name="Maven: org.springframework:spring-aop:4.3.13.RELEASE" level="project" />
  41 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-config:4.2.3.RELEASE" level="project" />
  42 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-web:4.2.3.RELEASE" level="project" />
  43 + <orderEntry type="library" name="Maven: org.springframework:spring-expression:4.3.13.RELEASE" level="project" />
  44 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-web:1.5.9.RELEASE" level="project" />
  45 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-tomcat:1.5.9.RELEASE" level="project" />
  46 + <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-core:8.5.23" level="project" />
  47 + <orderEntry type="library" name="Maven: org.apache.tomcat:tomcat-annotations-api:8.5.23" level="project" />
  48 + <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-el:8.5.23" level="project" />
  49 + <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-websocket:8.5.23" level="project" />
  50 + <orderEntry type="library" name="Maven: org.hibernate:hibernate-validator:5.3.6.Final" level="project" />
  51 + <orderEntry type="library" name="Maven: javax.validation:validation-api:1.1.0.Final" level="project" />
  52 + <orderEntry type="library" name="Maven: org.jboss.logging:jboss-logging:3.3.1.Final" level="project" />
  53 + <orderEntry type="library" name="Maven: com.fasterxml:classmate:1.3.4" level="project" />
  54 + <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.8.10" level="project" />
  55 + <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.8.0" level="project" />
  56 + <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.8.10" level="project" />
  57 + <orderEntry type="library" name="Maven: org.springframework:spring-web:4.3.13.RELEASE" level="project" />
  58 + <orderEntry type="library" name="Maven: org.springframework:spring-webmvc:4.3.13.RELEASE" level="project" />
  59 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-jwt:1.0.8.RELEASE" level="project" />
  60 + <orderEntry type="library" name="Maven: org.bouncycastle:bcpkix-jdk15on:1.56" level="project" />
  61 + <orderEntry type="library" name="Maven: org.bouncycastle:bcprov-jdk15on:1.56" level="project" />
  62 + <orderEntry type="module" module-name="oauth2-config" />
  63 + <orderEntry type="library" name="Maven: org.springframework.mobile:spring-mobile-device:1.1.5.RELEASE" level="project" />
  64 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-devtools:1.5.9.RELEASE" level="project" />
  65 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot:1.5.9.RELEASE" level="project" />
  66 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:1.5.9.RELEASE" level="project" />
  67 + <orderEntry type="library" scope="RUNTIME" name="Maven: com.h2database:h2:1.4.196" level="project" />
  68 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-jdbc:1.5.9.RELEASE" level="project" />
  69 + <orderEntry type="library" name="Maven: org.apache.tomcat:tomcat-jdbc:8.5.23" level="project" />
  70 + <orderEntry type="library" name="Maven: org.apache.tomcat:tomcat-juli:8.5.23" level="project" />
  71 + <orderEntry type="library" name="Maven: org.springframework:spring-jdbc:4.3.13.RELEASE" level="project" />
  72 + <orderEntry type="library" name="Maven: org.springframework:spring-tx:4.3.13.RELEASE" level="project" />
  73 + <orderEntry type="library" name="Maven: org.projectlombok:lombok:1.16.18" level="project" />
  74 + <orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-starter-test:1.5.9.RELEASE" level="project" />
  75 + <orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test:1.5.9.RELEASE" level="project" />
  76 + <orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test-autoconfigure:1.5.9.RELEASE" level="project" />
  77 + <orderEntry type="library" scope="TEST" name="Maven: com.jayway.jsonpath:json-path:2.2.0" level="project" />
  78 + <orderEntry type="library" scope="TEST" name="Maven: net.minidev:json-smart:2.2.1" level="project" />
  79 + <orderEntry type="library" scope="TEST" name="Maven: net.minidev:accessors-smart:1.1" level="project" />
  80 + <orderEntry type="library" scope="TEST" name="Maven: org.ow2.asm:asm:5.0.3" level="project" />
  81 + <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.25" level="project" />
  82 + <orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" />
  83 + <orderEntry type="library" scope="TEST" name="Maven: org.assertj:assertj-core:2.6.0" level="project" />
  84 + <orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-core:1.10.19" level="project" />
  85 + <orderEntry type="library" scope="TEST" name="Maven: org.objenesis:objenesis:2.1" level="project" />
  86 + <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
  87 + <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-library:1.3" level="project" />
  88 + <orderEntry type="library" scope="TEST" name="Maven: org.skyscreamer:jsonassert:1.4.0" level="project" />
  89 + <orderEntry type="library" scope="TEST" name="Maven: com.vaadin.external.google:android-json:0.0.20131108.vaadin1" level="project" />
  90 + <orderEntry type="library" name="Maven: org.springframework:spring-core:4.3.13.RELEASE" level="project" />
  91 + <orderEntry type="library" scope="TEST" name="Maven: org.springframework:spring-test:4.3.13.RELEASE" level="project" />
  92 + </component>
  93 +</module>
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4 + <modelVersion>4.0.0</modelVersion>
  5 +
  6 + <groupId>com.linyuan</groupId>
  7 + <artifactId>oauth2-demo</artifactId>
  8 + <version>0.0.1-SNAPSHOT</version>
  9 + <packaging>pom</packaging>
  10 +
  11 + <name>oauth2-demo</name>
  12 + <description>Demo project for Spring Boot</description>
  13 + <modules>
  14 + <module>authentication-server</module>
  15 + <module>resource1-server</module>
  16 + <module>resource2-server</module>
  17 + <module>oauth2-config</module>
  18 + </modules>
  19 +
  20 + <parent>
  21 + <groupId>org.springframework.boot</groupId>
  22 + <artifactId>spring-boot-starter-parent</artifactId>
  23 + <version>1.5.9.RELEASE</version>
  24 + <relativePath/> <!-- lookup parent from repository -->
  25 + </parent>
  26 +
  27 + <properties>
  28 + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  29 + <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  30 + <java.version>1.8</java.version>
  31 + <spring-cloud.version>Edgware.SR1</spring-cloud.version>
  32 + </properties>
  33 +
  34 + <dependencies>
  35 + <dependency>
  36 + <groupId>org.springframework.cloud</groupId>
  37 + <artifactId>spring-cloud-starter-oauth2</artifactId>
  38 + </dependency>
  39 + <dependency>
  40 + <groupId>org.springframework.boot</groupId>
  41 + <artifactId>spring-boot-starter-security</artifactId>
  42 + </dependency>
  43 + <dependency>
  44 + <groupId>org.springframework.boot</groupId>
  45 + <artifactId>spring-boot-starter-web</artifactId>
  46 + </dependency>
  47 + <dependency>
  48 + <groupId>org.springframework.security</groupId>
  49 + <artifactId>spring-security-jwt</artifactId>
  50 + </dependency>
  51 + <dependency>
  52 + <groupId>com.linyuan</groupId>
  53 + <artifactId>oauth2-config</artifactId>
  54 + <version>0.0.1-SNAPSHOT</version>
  55 + </dependency>
  56 + <dependency>
  57 + <groupId>org.springframework.mobile</groupId>
  58 + <artifactId>spring-mobile-device</artifactId>
  59 + </dependency>
  60 +
  61 + <dependency>
  62 + <groupId>org.springframework.boot</groupId>
  63 + <artifactId>spring-boot-devtools</artifactId>
  64 + <optional>true</optional>
  65 + <scope>true</scope>
  66 + </dependency>
  67 +
  68 + <dependency>
  69 + <groupId>com.h2database</groupId>
  70 + <artifactId>h2</artifactId>
  71 + <scope>runtime</scope>
  72 + </dependency>
  73 +
  74 + <dependency>
  75 + <groupId>org.springframework.boot</groupId>
  76 + <artifactId>spring-boot-starter-jdbc</artifactId>
  77 + </dependency>
  78 +
  79 + <dependency>
  80 + <groupId>org.projectlombok</groupId>
  81 + <artifactId>lombok</artifactId>
  82 + <optional>true</optional>
  83 + </dependency>
  84 + <dependency>
  85 + <groupId>org.springframework.boot</groupId>
  86 + <artifactId>spring-boot-starter-test</artifactId>
  87 + <scope>test</scope>
  88 + </dependency>
  89 +
  90 + </dependencies>
  91 +
  92 + <dependencyManagement>
  93 + <dependencies>
  94 + <dependency>
  95 + <groupId>org.springframework.cloud</groupId>
  96 + <artifactId>spring-cloud-dependencies</artifactId>
  97 + <version>${spring-cloud.version}</version>
  98 + <type>pom</type>
  99 + <scope>import</scope>
  100 + </dependency>
  101 + </dependencies>
  102 + </dependencyManagement>
  103 +
  104 + <build>
  105 + <plugins>
  106 + <plugin>
  107 + <groupId>org.springframework.boot</groupId>
  108 + <artifactId>spring-boot-maven-plugin</artifactId>
  109 + <configuration>
  110 + <fork>true</fork>
  111 + </configuration>
  112 + </plugin>
  113 + </plugins>
  114 + </build>
  115 +
  116 +
  117 +</project>
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4 + <parent>
  5 + <artifactId>oauth2-demo</artifactId>
  6 + <groupId>com.linyuan</groupId>
  7 + <version>0.0.1-SNAPSHOT</version>
  8 + <relativePath>../../oauth2-demo</relativePath>
  9 + </parent>
  10 + <modelVersion>4.0.0</modelVersion>
  11 +
  12 + <artifactId>resource1-server</artifactId>
  13 +</project>
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
  3 + <component name="FacetManager">
  4 + <facet type="Spring" name="Spring">
  5 + <configuration />
  6 + </facet>
  7 + </component>
  8 + <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
  9 + <output url="file://$MODULE_DIR$/target/classes" />
  10 + <output-test url="file://$MODULE_DIR$/target/test-classes" />
  11 + <content url="file://$MODULE_DIR$">
  12 + <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
  13 + <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
  14 + <sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
  15 + <excludeFolder url="file://$MODULE_DIR$/target" />
  16 + </content>
  17 + <orderEntry type="inheritedJdk" />
  18 + <orderEntry type="sourceFolder" forTests="false" />
  19 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-starter-oauth2:1.2.2.RELEASE" level="project" />
  20 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-starter-security:1.2.2.RELEASE" level="project" />
  21 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-starter:1.3.1.RELEASE" level="project" />
  22 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-context:1.3.1.RELEASE" level="project" />
  23 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-crypto:4.2.3.RELEASE" level="project" />
  24 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-commons:1.3.1.RELEASE" level="project" />
  25 + <orderEntry type="library" name="Maven: org.apache.httpcomponents:httpclient:4.5.3" level="project" />
  26 + <orderEntry type="library" name="Maven: org.apache.httpcomponents:httpcore:4.4.8" level="project" />
  27 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-rsa:1.0.3.RELEASE" level="project" />
  28 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-actuator:1.5.9.RELEASE" level="project" />
  29 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-actuator:1.5.9.RELEASE" level="project" />
  30 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-security:1.2.2.RELEASE" level="project" />
  31 + <orderEntry type="library" name="Maven: org.springframework.security.oauth:spring-security-oauth2:2.0.14.RELEASE" level="project" />
  32 + <orderEntry type="library" name="Maven: org.springframework:spring-beans:4.3.13.RELEASE" level="project" />
  33 + <orderEntry type="library" name="Maven: org.springframework:spring-context:4.3.13.RELEASE" level="project" />
  34 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-core:4.2.3.RELEASE" level="project" />
  35 + <orderEntry type="library" name="Maven: aopalliance:aopalliance:1.0" level="project" />
  36 + <orderEntry type="library" name="Maven: commons-codec:commons-codec:1.10" level="project" />
  37 + <orderEntry type="library" name="Maven: org.codehaus.jackson:jackson-mapper-asl:1.9.13" level="project" />
  38 + <orderEntry type="library" name="Maven: org.codehaus.jackson:jackson-core-asl:1.9.13" level="project" />
  39 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-security:1.5.9.RELEASE" level="project" />
  40 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:1.5.9.RELEASE" level="project" />
  41 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-logging:1.5.9.RELEASE" level="project" />
  42 + <orderEntry type="library" name="Maven: ch.qos.logback:logback-classic:1.1.11" level="project" />
  43 + <orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.1.11" level="project" />
  44 + <orderEntry type="library" name="Maven: org.slf4j:jcl-over-slf4j:1.7.25" level="project" />
  45 + <orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.25" level="project" />
  46 + <orderEntry type="library" name="Maven: org.slf4j:log4j-over-slf4j:1.7.25" level="project" />
  47 + <orderEntry type="library" scope="RUNTIME" name="Maven: org.yaml:snakeyaml:1.17" level="project" />
  48 + <orderEntry type="library" name="Maven: org.springframework:spring-aop:4.3.13.RELEASE" level="project" />
  49 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-config:4.2.3.RELEASE" level="project" />
  50 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-web:4.2.3.RELEASE" level="project" />
  51 + <orderEntry type="library" name="Maven: org.springframework:spring-expression:4.3.13.RELEASE" level="project" />
  52 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-web:1.5.9.RELEASE" level="project" />
  53 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-tomcat:1.5.9.RELEASE" level="project" />
  54 + <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-core:8.5.23" level="project" />
  55 + <orderEntry type="library" name="Maven: org.apache.tomcat:tomcat-annotations-api:8.5.23" level="project" />
  56 + <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-el:8.5.23" level="project" />
  57 + <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-websocket:8.5.23" level="project" />
  58 + <orderEntry type="library" name="Maven: org.hibernate:hibernate-validator:5.3.6.Final" level="project" />
  59 + <orderEntry type="library" name="Maven: javax.validation:validation-api:1.1.0.Final" level="project" />
  60 + <orderEntry type="library" name="Maven: org.jboss.logging:jboss-logging:3.3.1.Final" level="project" />
  61 + <orderEntry type="library" name="Maven: com.fasterxml:classmate:1.3.4" level="project" />
  62 + <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.8.10" level="project" />
  63 + <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.8.0" level="project" />
  64 + <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.8.10" level="project" />
  65 + <orderEntry type="library" name="Maven: org.springframework:spring-web:4.3.13.RELEASE" level="project" />
  66 + <orderEntry type="library" name="Maven: org.springframework:spring-webmvc:4.3.13.RELEASE" level="project" />
  67 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-jwt:1.0.8.RELEASE" level="project" />
  68 + <orderEntry type="library" name="Maven: org.bouncycastle:bcpkix-jdk15on:1.56" level="project" />
  69 + <orderEntry type="library" name="Maven: org.bouncycastle:bcprov-jdk15on:1.56" level="project" />
  70 + <orderEntry type="module" module-name="oauth2-config" />
  71 + <orderEntry type="library" name="Maven: org.springframework.mobile:spring-mobile-device:1.1.5.RELEASE" level="project" />
  72 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-devtools:1.5.9.RELEASE" level="project" />
  73 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot:1.5.9.RELEASE" level="project" />
  74 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:1.5.9.RELEASE" level="project" />
  75 + <orderEntry type="library" scope="RUNTIME" name="Maven: com.h2database:h2:1.4.196" level="project" />
  76 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-jdbc:1.5.9.RELEASE" level="project" />
  77 + <orderEntry type="library" name="Maven: org.apache.tomcat:tomcat-jdbc:8.5.23" level="project" />
  78 + <orderEntry type="library" name="Maven: org.apache.tomcat:tomcat-juli:8.5.23" level="project" />
  79 + <orderEntry type="library" name="Maven: org.springframework:spring-jdbc:4.3.13.RELEASE" level="project" />
  80 + <orderEntry type="library" name="Maven: org.springframework:spring-tx:4.3.13.RELEASE" level="project" />
  81 + <orderEntry type="library" name="Maven: org.projectlombok:lombok:1.16.18" level="project" />
  82 + <orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-starter-test:1.5.9.RELEASE" level="project" />
  83 + <orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test:1.5.9.RELEASE" level="project" />
  84 + <orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test-autoconfigure:1.5.9.RELEASE" level="project" />
  85 + <orderEntry type="library" scope="TEST" name="Maven: com.jayway.jsonpath:json-path:2.2.0" level="project" />
  86 + <orderEntry type="library" scope="TEST" name="Maven: net.minidev:json-smart:2.2.1" level="project" />
  87 + <orderEntry type="library" scope="TEST" name="Maven: net.minidev:accessors-smart:1.1" level="project" />
  88 + <orderEntry type="library" scope="TEST" name="Maven: org.ow2.asm:asm:5.0.3" level="project" />
  89 + <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.25" level="project" />
  90 + <orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" />
  91 + <orderEntry type="library" scope="TEST" name="Maven: org.assertj:assertj-core:2.6.0" level="project" />
  92 + <orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-core:1.10.19" level="project" />
  93 + <orderEntry type="library" scope="TEST" name="Maven: org.objenesis:objenesis:2.1" level="project" />
  94 + <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
  95 + <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-library:1.3" level="project" />
  96 + <orderEntry type="library" scope="TEST" name="Maven: org.skyscreamer:jsonassert:1.4.0" level="project" />
  97 + <orderEntry type="library" scope="TEST" name="Maven: com.vaadin.external.google:android-json:0.0.20131108.vaadin1" level="project" />
  98 + <orderEntry type="library" name="Maven: org.springframework:spring-core:4.3.13.RELEASE" level="project" />
  99 + <orderEntry type="library" scope="TEST" name="Maven: org.springframework:spring-test:4.3.13.RELEASE" level="project" />
  100 + </component>
  101 +</module>
  1 +package com.linyuan.resource1server;
  2 +
  3 +import com.linyuan.oauth2config.config.annotation.EnableResJWTTokenStore;
  4 +import org.springframework.boot.SpringApplication;
  5 +import org.springframework.boot.autoconfigure.SpringBootApplication;
  6 +import org.springframework.context.annotation.Bean;
  7 +import org.springframework.web.client.RestTemplate;
  8 +
  9 +@SpringBootApplication
  10 +@EnableResJWTTokenStore //OAuth2 使用 JWT 解析令牌
  11 +public class Resource1ServerApplication {
  12 +
  13 + @Bean
  14 + public RestTemplate restTemplate(){
  15 + return new RestTemplate();
  16 + }
  17 +
  18 + public static void main(String[] args) {
  19 + SpringApplication.run(Resource1ServerApplication.class, args);
  20 + }
  21 +}
  1 +package com.linyuan.resource1server.config;
  2 +
  3 +import com.linyuan.oauth2config.config.ResServerConfig;
  4 +import org.springframework.context.annotation.Configuration;
  5 +import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  6 +
  7 +/**
  8 + * @author: 林塬
  9 + * @date: 2018/1/18
  10 + * @description: 资源服务器访问权限配置
  11 + */
  12 +@Configuration
  13 +public class WebSecurityConfig extends ResServerConfig {
  14 +
  15 + @Override
  16 + public void configure(HttpSecurity http) throws Exception {
  17 + super.configure(http);
  18 + http
  19 + .authorizeRequests()
  20 + .antMatchers("/login").permitAll()
  21 + .antMatchers("/res","/res2/res")
  22 + .access("#oauth2.hasScope('read') and hasRole('USER')");
  23 + }
  24 +
  25 +}
  1 +package com.linyuan.resource1server.web.api.dto;
  2 +
  3 +import lombok.Data;
  4 +import org.hibernate.validator.constraints.NotBlank;
  5 +
  6 +import java.io.Serializable;
  7 +
  8 +/**
  9 + * @author: 林塬
  10 + * @date: 2018/1/15
  11 + * @description: 用户登录数据传输对象
  12 + */
  13 +@Data
  14 +public class LoginDTO implements Serializable {
  15 + @NotBlank(message = "用户名不能为空")
  16 + private String username;
  17 + @NotBlank(message = "密码不能为空")
  18 + private String password;
  19 +}
  1 +package com.linyuan.resource1server.web.rest;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import org.springframework.http.HttpEntity;
  5 +import org.springframework.http.HttpHeaders;
  6 +import org.springframework.http.HttpMethod;
  7 +import org.springframework.http.ResponseEntity;
  8 +import org.springframework.web.bind.annotation.GetMapping;
  9 +import org.springframework.web.bind.annotation.RestController;
  10 +import org.springframework.web.client.RestTemplate;
  11 +
  12 +import javax.servlet.http.HttpServletRequest;
  13 +
  14 +/**
  15 + * @author: 林塬
  16 + * @date: 2018/1/16
  17 + * @description: 资源服务器1-资源接口
  18 + */
  19 +@RestController
  20 +@AllArgsConstructor
  21 +public class ResController {
  22 +
  23 + private RestTemplate restTemplate;
  24 +
  25 + @GetMapping("/res")
  26 + public ResponseEntity<String> res(){
  27 + return ResponseEntity.ok("<h1>这是资源服务器1的受保护的资源</h1>");
  28 + }
  29 +
  30 + /**
  31 + * 访问资源服务器2-资源接口
  32 + * @param httpReq
  33 + * @return
  34 + */
  35 + @GetMapping("/res2/res")
  36 + public ResponseEntity<String> remoteRes(HttpServletRequest httpReq){
  37 + //HttpEntity
  38 + HttpHeaders httpHeaders = new HttpHeaders();
  39 + httpHeaders.set("Authorization",httpReq.getHeader("Authorization"));
  40 + HttpEntity httpEntity = new HttpEntity(httpHeaders);
  41 + //请求资源服务器2的资源
  42 + return restTemplate.exchange("http://localhost:9006/res",HttpMethod.GET,httpEntity,String.class);
  43 + }
  44 +
  45 +}
  1 +package com.linyuan.resource1server.web.rest;
  2 +
  3 +import com.linyuan.resource1server.web.api.dto.LoginDTO;
  4 +import lombok.AllArgsConstructor;
  5 +import org.springframework.boot.autoconfigure.security.oauth2.OAuth2ClientProperties;
  6 +import org.springframework.http.HttpEntity;
  7 +import org.springframework.http.HttpHeaders;
  8 +import org.springframework.http.HttpMethod;
  9 +import org.springframework.http.ResponseEntity;
  10 +import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
  11 +import org.springframework.security.oauth2.common.OAuth2AccessToken;
  12 +import org.springframework.util.LinkedMultiValueMap;
  13 +import org.springframework.util.MultiValueMap;
  14 +import org.springframework.validation.BindingResult;
  15 +import org.springframework.web.bind.annotation.PostMapping;
  16 +import org.springframework.web.bind.annotation.RequestBody;
  17 +import org.springframework.web.bind.annotation.RestController;
  18 +import org.springframework.web.client.RestTemplate;
  19 +
  20 +import javax.validation.Valid;
  21 +import java.util.Base64;
  22 +import java.util.Collections;
  23 +
  24 +/**
  25 + * @author: 林塬
  26 + * @date: 2018/1/16
  27 + * @description: 令牌管理接口
  28 + */
  29 +@RestController
  30 +@AllArgsConstructor
  31 +public class TokenController {
  32 +
  33 + private OAuth2ClientProperties oAuth2ClientProperties;
  34 +
  35 + private OAuth2ProtectedResourceDetails oAuth2ProtectedResourceDetails;
  36 +
  37 + private RestTemplate restTemplate;
  38 +
  39 + /**
  40 + * 通过密码授权方式向授权服务器获取令牌
  41 + * @param loginDTO
  42 + * @param bindingResult
  43 + * @return
  44 + * @throws Exception
  45 + */
  46 + @PostMapping(value = "/login")
  47 + public ResponseEntity<OAuth2AccessToken> login(@RequestBody @Valid LoginDTO loginDTO, BindingResult bindingResult) throws Exception{
  48 + if (bindingResult.hasErrors()) {
  49 + throw new Exception("登录信息格式错误");
  50 + } else {
  51 + //Http Basic 验证
  52 + String clientAndSecret = oAuth2ClientProperties.getClientId()+":"+oAuth2ClientProperties.getClientSecret();
  53 + //这里需要注意为 Basic 而非 Bearer
  54 + clientAndSecret = "Basic "+Base64.getEncoder().encodeToString(clientAndSecret.getBytes());
  55 + HttpHeaders httpHeaders = new HttpHeaders();
  56 + httpHeaders.set("Authorization",clientAndSecret);
  57 + //授权请求信息
  58 + MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
  59 + map.put("username", Collections.singletonList(loginDTO.getUsername()));
  60 + map.put("password", Collections.singletonList(loginDTO.getPassword()));
  61 + map.put("grant_type", Collections.singletonList(oAuth2ProtectedResourceDetails.getGrantType()));
  62 + map.put("scope", oAuth2ProtectedResourceDetails.getScope());
  63 + //HttpEntity
  64 + HttpEntity httpEntity = new HttpEntity(map,httpHeaders);
  65 + //获取 Token
  66 + return restTemplate.exchange(oAuth2ProtectedResourceDetails.getAccessTokenUri(), HttpMethod.POST,httpEntity,OAuth2AccessToken.class);
  67 + }
  68 + }
  69 +}
  1 +server:
  2 + port: 9007
  3 +security:
  4 + oauth2:
  5 + client:
  6 + clientId: resource1
  7 + clientSecret: secret
  8 + userAuthorizationUri: http://localhost:9005/oauth/authorize
  9 + grant-type: password
  10 + scope: read
  11 + access-token-uri: http://localhost:9005/oauth/token
  12 + resource:
  13 + jwt:
  14 + key-uri: http://localhost:9005/oauth/token_key
  15 + basic:
  16 + enabled: false
  1 +-----BEGIN PUBLIC KEY-----
  2 +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzkG04GeFhYUw7trgPn4db3/5TbWwFcd8M3tpOwqwpjzGGkXzguWPQ/Qkre0ob58JPt9tJHNTiUqTf2zJVKXZZ/38U4BJvcsQMR5n5VOtTxO1OglQmXQREundsMYksNxf32kOnE2eeX2jKNg3X/zeehCK3V7nPwFXFk6lCk1mRFSrretD5cBkNQLR2l9zmLNnBmWIY3DWb3qM/SqV7rBYEdl2OJOqshBp/jlAUeWlFgULMqRmJtoSt1u7/6gRCe8o39H1dvuqAu7MdwrOqlDFm5EOTYLGTONyD6xNwm2BBd2v3cF/DfPAot0442GHW31+3GNP/KnuGfN1OfKFT/7cdQIDAQAB
  3 +-----END PUBLIC KEY-----
  1 +package com.linyuan.resource1server.web.rest;
  2 +
  3 +import com.linyuan.resource1server.Resource1ServerApplication;
  4 +import com.linyuan.resource1server.web.api.dto.LoginDTO;
  5 +import lombok.extern.slf4j.Slf4j;
  6 +import org.apache.http.HttpStatus;
  7 +import org.codehaus.jackson.map.ObjectMapper;
  8 +import org.junit.Assert;
  9 +import org.junit.Before;
  10 +import org.junit.Test;
  11 +import org.junit.runner.RunWith;
  12 +import org.springframework.beans.factory.annotation.Autowired;
  13 +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
  14 +import org.springframework.boot.test.context.SpringBootTest;
  15 +import org.springframework.http.MediaType;
  16 +import org.springframework.security.oauth2.common.OAuth2AccessToken;
  17 +import org.springframework.test.context.junit4.SpringRunner;
  18 +import org.springframework.test.web.servlet.MockMvc;
  19 +
  20 +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
  21 +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
  22 +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
  23 +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
  24 +
  25 +/**
  26 + * @author: 林塬
  27 + * @date: 2018/1/19
  28 + * @description: 资源获取单元测试
  29 + */
  30 +@Slf4j
  31 +@RunWith(SpringRunner.class)
  32 +@SpringBootTest(classes = Resource1ServerApplication.class)
  33 +@AutoConfigureMockMvc
  34 +public class ResControllerTest {
  35 +
  36 + @Autowired
  37 + private MockMvc mockMvc;
  38 +
  39 + private ObjectMapper objectMapper = new ObjectMapper();
  40 +
  41 + private OAuth2AccessToken oAuth2AccessToken;
  42 +
  43 + /**
  44 + * 获取令牌
  45 + * @throws Exception
  46 + */
  47 + @Before
  48 + public void getToken() throws Exception {
  49 + LoginDTO loginDTO = new LoginDTO();
  50 + loginDTO.setUsername("linyuan");
  51 + loginDTO.setPassword("123456");
  52 +
  53 + byte[] body = this.mockMvc.perform(
  54 + post("/login")
  55 + .content(objectMapper.writeValueAsBytes(loginDTO))
  56 + .contentType(MediaType.APPLICATION_JSON) //请求数据的格式
  57 + .accept(MediaType.APPLICATION_JSON) //接收返回数据的格式
  58 + ).andExpect(status().isOk())
  59 + .andReturn().getResponse().getContentAsByteArray();
  60 + oAuth2AccessToken = objectMapper.readValue(body,OAuth2AccessToken.class);
  61 + }
  62 +
  63 + /**
  64 + * 测试访问本地受保护资源
  65 + * @throws Exception
  66 + */
  67 + @Test
  68 + public void testGetLocalRes() throws Exception{
  69 + int status = this.mockMvc.perform(
  70 + get("/res")
  71 + .header("Authorization",OAuth2AccessToken.BEARER_TYPE+" "+oAuth2AccessToken.getValue())
  72 + .accept(MediaType.APPLICATION_JSON)
  73 + ).andDo(print()).andReturn().getResponse().getStatus();
  74 + printStatus(status);
  75 + Assert.assertEquals(status,HttpStatus.SC_OK);
  76 + }
  77 +
  78 + /**
  79 + * 测试访问资源服务器2受保护资源
  80 + * @throws Exception
  81 + */
  82 + @Test
  83 + public void testGetRes2lRes() throws Exception{
  84 + int status = this.mockMvc.perform(
  85 + get("/res2/res")
  86 + .header("Authorization",OAuth2AccessToken.BEARER_TYPE+" "+oAuth2AccessToken.getValue())
  87 + .accept(MediaType.APPLICATION_JSON)
  88 + ).andDo(print()).andReturn().getResponse().getStatus();
  89 + printStatus(status);
  90 + Assert.assertEquals(status,HttpStatus.SC_OK);
  91 + }
  92 +
  93 + private void printStatus(int status){
  94 + switch (status) {
  95 + case HttpStatus.SC_OK:
  96 + log.info("测试访问受保护资源---------------->成功(200)");
  97 + break;
  98 + case HttpStatus.SC_UNAUTHORIZED:
  99 + log.info("测试访问受保护资源---------------->失败(401---没有权限,请确认令牌无误,角色权限无误,请注意是否 Authorization 请求头部 Basic 打成了 Bearer)");
  100 + break;
  101 + case HttpStatus.SC_BAD_REQUEST:
  102 + log.info("测试访问受保护资源---------------->失败(400---请求失败,请检查用户密码是否正确)");
  103 + break;
  104 + default:
  105 + log.info("测试访问本地受保护资源---------------->失败({}---未知结果)",status);
  106 + break;
  107 + }
  108 + }
  109 +}
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4 + <parent>
  5 + <artifactId>oauth2-demo</artifactId>
  6 + <groupId>com.linyuan</groupId>
  7 + <version>0.0.1-SNAPSHOT</version>
  8 + <relativePath>../../oauth2-demo</relativePath>
  9 + </parent>
  10 + <modelVersion>4.0.0</modelVersion>
  11 +
  12 + <artifactId>resource2-server</artifactId>
  13 +</project>
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
  3 + <component name="FacetManager">
  4 + <facet type="Spring" name="Spring">
  5 + <configuration />
  6 + </facet>
  7 + </component>
  8 + <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_8">
  9 + <output url="file://$MODULE_DIR$/target/classes" />
  10 + <output-test url="file://$MODULE_DIR$/target/test-classes" />
  11 + <content url="file://$MODULE_DIR$">
  12 + <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
  13 + <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
  14 + <excludeFolder url="file://$MODULE_DIR$/target" />
  15 + </content>
  16 + <orderEntry type="inheritedJdk" />
  17 + <orderEntry type="sourceFolder" forTests="false" />
  18 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-starter-oauth2:1.2.2.RELEASE" level="project" />
  19 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-starter-security:1.2.2.RELEASE" level="project" />
  20 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-starter:1.3.1.RELEASE" level="project" />
  21 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-context:1.3.1.RELEASE" level="project" />
  22 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-crypto:4.2.3.RELEASE" level="project" />
  23 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-commons:1.3.1.RELEASE" level="project" />
  24 + <orderEntry type="library" name="Maven: org.apache.httpcomponents:httpclient:4.5.3" level="project" />
  25 + <orderEntry type="library" name="Maven: org.apache.httpcomponents:httpcore:4.4.8" level="project" />
  26 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-rsa:1.0.3.RELEASE" level="project" />
  27 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-actuator:1.5.9.RELEASE" level="project" />
  28 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-actuator:1.5.9.RELEASE" level="project" />
  29 + <orderEntry type="library" name="Maven: org.springframework.cloud:spring-cloud-security:1.2.2.RELEASE" level="project" />
  30 + <orderEntry type="library" name="Maven: org.springframework.security.oauth:spring-security-oauth2:2.0.14.RELEASE" level="project" />
  31 + <orderEntry type="library" name="Maven: org.springframework:spring-beans:4.3.13.RELEASE" level="project" />
  32 + <orderEntry type="library" name="Maven: org.springframework:spring-context:4.3.13.RELEASE" level="project" />
  33 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-core:4.2.3.RELEASE" level="project" />
  34 + <orderEntry type="library" name="Maven: aopalliance:aopalliance:1.0" level="project" />
  35 + <orderEntry type="library" name="Maven: commons-codec:commons-codec:1.10" level="project" />
  36 + <orderEntry type="library" name="Maven: org.codehaus.jackson:jackson-mapper-asl:1.9.13" level="project" />
  37 + <orderEntry type="library" name="Maven: org.codehaus.jackson:jackson-core-asl:1.9.13" level="project" />
  38 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-security:1.5.9.RELEASE" level="project" />
  39 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter:1.5.9.RELEASE" level="project" />
  40 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-logging:1.5.9.RELEASE" level="project" />
  41 + <orderEntry type="library" name="Maven: ch.qos.logback:logback-classic:1.1.11" level="project" />
  42 + <orderEntry type="library" name="Maven: ch.qos.logback:logback-core:1.1.11" level="project" />
  43 + <orderEntry type="library" name="Maven: org.slf4j:jcl-over-slf4j:1.7.25" level="project" />
  44 + <orderEntry type="library" name="Maven: org.slf4j:jul-to-slf4j:1.7.25" level="project" />
  45 + <orderEntry type="library" name="Maven: org.slf4j:log4j-over-slf4j:1.7.25" level="project" />
  46 + <orderEntry type="library" scope="RUNTIME" name="Maven: org.yaml:snakeyaml:1.17" level="project" />
  47 + <orderEntry type="library" name="Maven: org.springframework:spring-aop:4.3.13.RELEASE" level="project" />
  48 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-config:4.2.3.RELEASE" level="project" />
  49 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-web:4.2.3.RELEASE" level="project" />
  50 + <orderEntry type="library" name="Maven: org.springframework:spring-expression:4.3.13.RELEASE" level="project" />
  51 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-web:1.5.9.RELEASE" level="project" />
  52 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-tomcat:1.5.9.RELEASE" level="project" />
  53 + <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-core:8.5.23" level="project" />
  54 + <orderEntry type="library" name="Maven: org.apache.tomcat:tomcat-annotations-api:8.5.23" level="project" />
  55 + <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-el:8.5.23" level="project" />
  56 + <orderEntry type="library" name="Maven: org.apache.tomcat.embed:tomcat-embed-websocket:8.5.23" level="project" />
  57 + <orderEntry type="library" name="Maven: org.hibernate:hibernate-validator:5.3.6.Final" level="project" />
  58 + <orderEntry type="library" name="Maven: javax.validation:validation-api:1.1.0.Final" level="project" />
  59 + <orderEntry type="library" name="Maven: org.jboss.logging:jboss-logging:3.3.1.Final" level="project" />
  60 + <orderEntry type="library" name="Maven: com.fasterxml:classmate:1.3.4" level="project" />
  61 + <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-databind:2.8.10" level="project" />
  62 + <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-annotations:2.8.0" level="project" />
  63 + <orderEntry type="library" name="Maven: com.fasterxml.jackson.core:jackson-core:2.8.10" level="project" />
  64 + <orderEntry type="library" name="Maven: org.springframework:spring-web:4.3.13.RELEASE" level="project" />
  65 + <orderEntry type="library" name="Maven: org.springframework:spring-webmvc:4.3.13.RELEASE" level="project" />
  66 + <orderEntry type="library" name="Maven: org.springframework.security:spring-security-jwt:1.0.8.RELEASE" level="project" />
  67 + <orderEntry type="library" name="Maven: org.bouncycastle:bcpkix-jdk15on:1.56" level="project" />
  68 + <orderEntry type="library" name="Maven: org.bouncycastle:bcprov-jdk15on:1.56" level="project" />
  69 + <orderEntry type="module" module-name="oauth2-config" />
  70 + <orderEntry type="library" name="Maven: org.springframework.mobile:spring-mobile-device:1.1.5.RELEASE" level="project" />
  71 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-devtools:1.5.9.RELEASE" level="project" />
  72 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot:1.5.9.RELEASE" level="project" />
  73 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-autoconfigure:1.5.9.RELEASE" level="project" />
  74 + <orderEntry type="library" scope="RUNTIME" name="Maven: com.h2database:h2:1.4.196" level="project" />
  75 + <orderEntry type="library" name="Maven: org.springframework.boot:spring-boot-starter-jdbc:1.5.9.RELEASE" level="project" />
  76 + <orderEntry type="library" name="Maven: org.apache.tomcat:tomcat-jdbc:8.5.23" level="project" />
  77 + <orderEntry type="library" name="Maven: org.apache.tomcat:tomcat-juli:8.5.23" level="project" />
  78 + <orderEntry type="library" name="Maven: org.springframework:spring-jdbc:4.3.13.RELEASE" level="project" />
  79 + <orderEntry type="library" name="Maven: org.springframework:spring-tx:4.3.13.RELEASE" level="project" />
  80 + <orderEntry type="library" name="Maven: org.projectlombok:lombok:1.16.18" level="project" />
  81 + <orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-starter-test:1.5.9.RELEASE" level="project" />
  82 + <orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test:1.5.9.RELEASE" level="project" />
  83 + <orderEntry type="library" scope="TEST" name="Maven: org.springframework.boot:spring-boot-test-autoconfigure:1.5.9.RELEASE" level="project" />
  84 + <orderEntry type="library" scope="TEST" name="Maven: com.jayway.jsonpath:json-path:2.2.0" level="project" />
  85 + <orderEntry type="library" scope="TEST" name="Maven: net.minidev:json-smart:2.2.1" level="project" />
  86 + <orderEntry type="library" scope="TEST" name="Maven: net.minidev:accessors-smart:1.1" level="project" />
  87 + <orderEntry type="library" scope="TEST" name="Maven: org.ow2.asm:asm:5.0.3" level="project" />
  88 + <orderEntry type="library" name="Maven: org.slf4j:slf4j-api:1.7.25" level="project" />
  89 + <orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.12" level="project" />
  90 + <orderEntry type="library" scope="TEST" name="Maven: org.assertj:assertj-core:2.6.0" level="project" />
  91 + <orderEntry type="library" scope="TEST" name="Maven: org.mockito:mockito-core:1.10.19" level="project" />
  92 + <orderEntry type="library" scope="TEST" name="Maven: org.objenesis:objenesis:2.1" level="project" />
  93 + <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-core:1.3" level="project" />
  94 + <orderEntry type="library" scope="TEST" name="Maven: org.hamcrest:hamcrest-library:1.3" level="project" />
  95 + <orderEntry type="library" scope="TEST" name="Maven: org.skyscreamer:jsonassert:1.4.0" level="project" />
  96 + <orderEntry type="library" scope="TEST" name="Maven: com.vaadin.external.google:android-json:0.0.20131108.vaadin1" level="project" />
  97 + <orderEntry type="library" name="Maven: org.springframework:spring-core:4.3.13.RELEASE" level="project" />
  98 + <orderEntry type="library" scope="TEST" name="Maven: org.springframework:spring-test:4.3.13.RELEASE" level="project" />
  99 + </component>
  100 +</module>
  1 +package com.linyuan.resource2server;
  2 +
  3 +import com.linyuan.oauth2config.config.annotation.EnableResJWTTokenStore;
  4 +import org.springframework.boot.SpringApplication;
  5 +import org.springframework.boot.autoconfigure.SpringBootApplication;
  6 +
  7 +@SpringBootApplication
  8 +@EnableResJWTTokenStore //OAuth2 使用 JWT 解析令牌
  9 +public class Resource2ServerApplication {
  10 +
  11 + public static void main(String[] args) {
  12 + SpringApplication.run(Resource2ServerApplication.class, args);
  13 + }
  14 +}
  1 +package com.linyuan.resource2server.config;
  2 +
  3 +import com.linyuan.oauth2config.config.ResServerConfig;
  4 +import org.springframework.context.annotation.Configuration;
  5 +import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  6 +
  7 +/**
  8 + * @author: 林塬
  9 + * @date: 2018/1/11
  10 + * @description: 资源服务器访问权限配置
  11 + */
  12 +@Configuration
  13 +public class WebSecurityConfig extends ResServerConfig{
  14 +
  15 + @Override
  16 + public void configure(HttpSecurity http) throws Exception {
  17 + super.configure(http);
  18 + http.authorizeRequests()
  19 + //访问受保护资源 /res 的要求:客户端 Scope 为 read,用户本身角色为 USER
  20 + .antMatchers("/res")
  21 + .access("#oauth2.hasScope('read') and hasRole('USER')");
  22 + }
  23 +
  24 +}
  1 +package com.linyuan.resource2server.rest;
  2 +
  3 +import org.springframework.http.ResponseEntity;
  4 +import org.springframework.web.bind.annotation.GetMapping;
  5 +import org.springframework.web.bind.annotation.RestController;
  6 +
  7 +/**
  8 + * @author: 林塬
  9 + * @date: 2018/1/16
  10 + * @description: 资源服务器2-资源接口
  11 + */
  12 +@RestController
  13 +public class ResController {
  14 +
  15 + @GetMapping("/res")
  16 + public ResponseEntity<String> res(){
  17 + return ResponseEntity.ok("<h1>这是资源服务器2的受保护的资源</h1>");
  18 + }
  19 +
  20 +}
  1 +server:
  2 + port: 9006
  3 +security:
  4 + oauth2:
  5 + resource:
  6 + jwt:
  7 + key-uri: http://localhost:9005/oauth/token_key
  1 +-----BEGIN PUBLIC KEY-----
  2 +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzkG04GeFhYUw7trgPn4db3/5TbWwFcd8M3tpOwqwpjzGGkXzguWPQ/Qkre0ob58JPt9tJHNTiUqTf2zJVKXZZ/38U4BJvcsQMR5n5VOtTxO1OglQmXQREundsMYksNxf32kOnE2eeX2jKNg3X/zeehCK3V7nPwFXFk6lCk1mRFSrretD5cBkNQLR2l9zmLNnBmWIY3DWb3qM/SqV7rBYEdl2OJOqshBp/jlAUeWlFgULMqRmJtoSt1u7/6gRCe8o39H1dvuqAu7MdwrOqlDFm5EOTYLGTONyD6xNwm2BBd2v3cF/DfPAot0442GHW31+3GNP/KnuGfN1OfKFT/7cdQIDAQAB
  3 +-----END PUBLIC KEY-----