├── README.md ├── .gitignore ├── jwt-resource-server ├── src │ └── main │ │ ├── resources │ │ └── application.yml │ │ └── java │ │ └── com │ │ └── cheng │ │ └── resource │ │ └── ResourceServerApplication.java └── pom.xml ├── auth-server ├── src │ └── main │ │ ├── resources │ │ ├── application.yml │ │ └── templates │ │ │ ├── index.html │ │ │ └── login.html │ │ └── java │ │ └── com │ │ └── cheng │ │ └── auth │ │ └── AuthServerApplication.java └── pom.xml ├── resource-server ├── src │ └── main │ │ ├── resources │ │ └── application.yml │ │ └── java │ │ └── com │ │ └── cheng │ │ └── resource │ │ └── ResourceServerApplication.java └── pom.xml ├── ui ├── src │ └── main │ │ ├── resources │ │ ├── application.yml │ │ └── templates │ │ │ └── index.html │ │ └── java │ │ └── com │ │ └── cheng │ │ └── ui │ │ └── UiApplication.java └── pom.xml ├── jwt-auth-server ├── src │ └── main │ │ ├── resources │ │ ├── templates │ │ │ ├── index.html │ │ │ └── login.html │ │ └── application.yml │ │ └── java │ │ └── com │ │ └── cheng │ │ └── auth │ │ └── AuthServerApplication.java └── pom.xml └── pom.xml /README.md: -------------------------------------------------------------------------------- 1 | # oauth2-sso 2 | 3 | 基于Spring Boot + Spring Security OAuth2 + JWT 搭建的单点登录示例 4 | 5 | 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | logs/ 3 | 4 | ### STS ### 5 | .apt_generated 6 | .classpath 7 | .factorypath 8 | .project 9 | .settings 10 | .springBeans 11 | 12 | ### IntelliJ IDEA ### 13 | .idea 14 | *.iws 15 | *.iml 16 | *.ipr 17 | -------------------------------------------------------------------------------- /jwt-resource-server/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | logging: 2 | file: logs/oath2-sso.log 3 | level: 4 | root: info 5 | 6 | server: 7 | port: 9992 8 | 9 | spring: 10 | jackson: 11 | date-format: com.fasterxml.jackson.databind.util.ISO8601DateFormat 12 | 13 | security: 14 | oauth2: 15 | resource: 16 | jwt: 17 | key-uri: ${auth-server:http://localhost:9991/uaa}/oauth/token_key 18 | -------------------------------------------------------------------------------- /auth-server/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | logging: 2 | file: logs/oath2-sso.log 3 | level: 4 | root: info 5 | org.springframework.security: DEBUG 6 | 7 | server: 8 | port: 9991 9 | context-path: /uaa 10 | 11 | security: 12 | user: 13 | password: password 14 | oauth2: 15 | client: 16 | client-id: demo 17 | client-secret: demo 18 | scope: read, write 19 | auto-approve-scopes: .* 20 | authorization: 21 | check-token-access: permitAll() -------------------------------------------------------------------------------- /resource-server/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | logging: 2 | file: logs/oath2-sso.log 3 | level: 4 | root: info 5 | 6 | server: 7 | port: 9992 8 | 9 | spring: 10 | jackson: 11 | date-format: com.fasterxml.jackson.databind.util.ISO8601DateFormat 12 | 13 | security: 14 | oauth2: 15 | resource: 16 | token-info-uri: ${auth-server:http://localhost:9991/uaa}/oauth/check_token 17 | jwt: 18 | key-uri: ${auth-server:http://localhost:9999/uaa}/oauth/token_key 19 | client: 20 | client-id: demo 21 | client-secret: demo -------------------------------------------------------------------------------- /ui/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | logging: 2 | file: logs/oath2-sso.log 3 | level: 4 | root: info 5 | org.springframework.security: DEBUG 6 | 7 | server: 8 | port: 9993 9 | 10 | spring: 11 | jackson: 12 | date-format: com.fasterxml.jackson.databind.util.ISO8601DateFormat 13 | 14 | auth-server: http://localhost:9991/uaa 15 | 16 | security: 17 | basic: 18 | enabled: false 19 | oauth2: 20 | client: 21 | client-id: demo 22 | client-secret: demo 23 | access-token-uri: ${auth-server}/oauth/token 24 | user-authorization-uri: ${auth-server}/oauth/authorize 25 | scope: read, write 26 | resource: 27 | token-info-uri: ${auth-server}/oauth/check_token 28 | jwt: 29 | key-uri: ${auth-server}/oauth/token_key 30 | -------------------------------------------------------------------------------- /auth-server/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | OAuth2 SSO Demo 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |
14 |

Demo

15 | Go back to UI 16 |
17 | 18 |
19 |
20 |
21 |
22 | 23 | -------------------------------------------------------------------------------- /jwt-auth-server/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | OAuth2 SSO Demo 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |
14 |

Demo

15 | Go back to UI 16 |
17 | 18 |
19 |
20 |
21 |
22 | 23 | -------------------------------------------------------------------------------- /ui/src/main/resources/templates/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | OAuth2 SSO Demo 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |
14 |

Demo

15 |

Logged in as: demo

16 |
17 | 18 | 19 |
20 |

Messages

21 |
22 |

@

24 | 25 |
26 |
27 |
28 |
29 | 30 | -------------------------------------------------------------------------------- /ui/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | oauth2-sso 7 | com.cheng 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | ui 13 | 14 | 15 | 16 | org.springframework.cloud 17 | spring-cloud-starter-oauth2 18 | 19 | 20 | org.springframework.boot 21 | spring-boot-starter-security 22 | 23 | 24 | org.springframework.boot 25 | spring-boot-starter-thymeleaf 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter-web 30 | 31 | 32 | com.fasterxml.jackson.datatype 33 | jackson-datatype-jsr310 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /resource-server/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | oauth2-sso 7 | com.cheng 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | resource-server 13 | 14 | 15 | 16 | org.springframework.boot 17 | spring-boot-starter-actuator 18 | 19 | 20 | org.springframework.cloud 21 | spring-cloud-starter-oauth2 22 | 23 | 24 | org.springframework.boot 25 | spring-boot-starter-security 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter-web 30 | 31 | 32 | com.fasterxml.jackson.datatype 33 | jackson-datatype-jsr310 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /jwt-resource-server/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | oauth2-sso 7 | com.cheng 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | jwt-resource-server 13 | 14 | 15 | 16 | org.springframework.boot 17 | spring-boot-starter-actuator 18 | 19 | 20 | org.springframework.cloud 21 | spring-cloud-starter-oauth2 22 | 23 | 24 | org.springframework.boot 25 | spring-boot-starter-security 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter-web 30 | 31 | 32 | com.fasterxml.jackson.datatype 33 | jackson-datatype-jsr310 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /auth-server/src/main/resources/templates/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | OAuth2 SSO Demo 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |

Login Form

14 | 15 |

16 | Login failed ... 17 |

18 | 19 |

20 | Logout succeeded. 21 |

22 | 23 |
24 |
25 | 27 |
28 |
29 | 31 |
32 |
33 | 34 |
35 |
36 | 37 |
38 |
39 | 40 | -------------------------------------------------------------------------------- /jwt-auth-server/src/main/resources/templates/login.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | OAuth2 SSO Demo 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |

Login Form

14 | 15 |

16 | Login failed ... 17 |

18 | 19 |

20 | Logout succeeded. 21 |

22 | 23 |
24 |
25 | 27 |
28 |
29 | 31 |
32 |
33 | 34 |
35 |
36 | 37 |
38 |
39 | 40 | -------------------------------------------------------------------------------- /auth-server/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | oauth2-sso 7 | com.cheng 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | auth-server 13 | 14 | 15 | 16 | 17 | org.springframework.boot 18 | spring-boot-starter 19 | 20 | 21 | org.springframework.boot 22 | spring-boot-starter-web 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-thymeleaf 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-actuator 31 | 32 | 33 | org.springframework.cloud 34 | spring-cloud-starter-oauth2 35 | 36 | 37 | org.springframework.boot 38 | spring-boot-starter-security 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /jwt-auth-server/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | oauth2-sso 7 | com.cheng 8 | 1.0-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | jwt-auth-server 13 | 14 | 15 | 16 | org.springframework.boot 17 | spring-boot-starter-actuator 18 | 19 | 20 | org.springframework.cloud 21 | spring-cloud-starter-oauth2 22 | 23 | 24 | org.springframework.boot 25 | spring-boot-starter-security 26 | 27 | 28 | org.springframework.boot 29 | spring-boot-starter-thymeleaf 30 | 31 | 32 | org.springframework.boot 33 | spring-boot-starter-web 34 | 35 | 36 | org.springframework.boot 37 | spring-boot-devtools 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-starter-test 42 | test 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /auth-server/src/main/java/com/cheng/auth/AuthServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.cheng.auth; 2 | 3 | import org.apache.catalina.filters.RequestDumperFilter; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import org.springframework.context.annotation.Profile; 9 | import org.springframework.core.annotation.Order; 10 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 11 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 12 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; 13 | import org.springframework.web.bind.annotation.RestController; 14 | import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; 15 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 16 | 17 | /** 18 | * @author fengcheng 19 | * @version 2017/8/24 20 | */ 21 | @SpringBootApplication 22 | @EnableAuthorizationServer 23 | @RestController 24 | public class AuthServerApplication { 25 | 26 | public static void main(String[] args) { 27 | SpringApplication.run(AuthServerApplication.class, args); 28 | } 29 | 30 | @Configuration 31 | static class MvcConfig extends WebMvcConfigurerAdapter { 32 | @Override 33 | public void addViewControllers(ViewControllerRegistry registry) { 34 | registry.addViewController("login").setViewName("login"); 35 | registry.addViewController("/").setViewName("index"); 36 | } 37 | } 38 | 39 | @Configuration 40 | @Order(-20) 41 | static class LoginConfig extends WebSecurityConfigurerAdapter { 42 | @Override 43 | protected void configure(HttpSecurity http) throws Exception { 44 | http 45 | .formLogin().loginPage("/login").permitAll() 46 | .and() 47 | .requestMatchers() 48 | .antMatchers("/", "/login", "/oauth/authorize", "/oauth/confirm_access") 49 | .and() 50 | .authorizeRequests() 51 | .anyRequest().authenticated(); 52 | } 53 | } 54 | 55 | @Profile("!cloud") 56 | @Bean 57 | RequestDumperFilter requestDumperFilter() { 58 | return new RequestDumperFilter(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /jwt-auth-server/src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | logging: 2 | file: logs/oath2-sso.log 3 | level: 4 | root: info 5 | org.springframework.security: DEBUG 6 | 7 | server: 8 | port: 9991 9 | context-path: /uaa 10 | 11 | security: 12 | user: 13 | password: password 14 | oauth2: 15 | authorization: 16 | token-key-access: permitAll() 17 | 18 | # openssl genrsa -out private.pem 2048 19 | # openssl rsa -in private.pem -outform PEM -pubout -out public.pem 20 | jwt: 21 | verifier-key: | 22 | -----BEGIN PUBLIC KEY----- 23 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA36clBU2NYn5iZG/swkq3 24 | rtUUrXoGSrlvpxfmFpFp6bg9xu/378pi+8UC54DMBka+m/hJIvdl7dpwWFw6tWcg 25 | mXJ59zljwgG+VbkKrtQVwsQYsjh++vUKj9oGmtCZX7UE/Rnc7k6w/HMPUalu9gIT 26 | x3hXo+sWfWHQYHhKs5sjKJtTixHJ29Rqp5U87iZTPosVaIBzkOcRqM905o5JmAHP 27 | 9pcR3Gy59eb4r3KJgIqssv7OcVG0PA3Qd7iNIMnhbz0VaQjbibf9b3btEsc2J8Vl 28 | wfxX4DC8V3b2J/IqxQP3oJ0eAMvygVR9mkmHGPxy1dA+0OIeM+3nUsFzL3QyZMYD 29 | /wIDAQAB 30 | -----END PUBLIC KEY----- 31 | signing-key: | 32 | -----BEGIN RSA PRIVATE KEY----- 33 | MIIEowIBAAKCAQEA36clBU2NYn5iZG/swkq3rtUUrXoGSrlvpxfmFpFp6bg9xu/3 34 | 78pi+8UC54DMBka+m/hJIvdl7dpwWFw6tWcgmXJ59zljwgG+VbkKrtQVwsQYsjh+ 35 | +vUKj9oGmtCZX7UE/Rnc7k6w/HMPUalu9gITx3hXo+sWfWHQYHhKs5sjKJtTixHJ 36 | 29Rqp5U87iZTPosVaIBzkOcRqM905o5JmAHP9pcR3Gy59eb4r3KJgIqssv7OcVG0 37 | PA3Qd7iNIMnhbz0VaQjbibf9b3btEsc2J8VlwfxX4DC8V3b2J/IqxQP3oJ0eAMvy 38 | gVR9mkmHGPxy1dA+0OIeM+3nUsFzL3QyZMYD/wIDAQABAoIBABwVG7Pnwfn9DpO3 39 | 7g2TXi8IuFjz+nhFgnyDprNsvNTI+pDRLtugGP+uBChXZsbe+S4SZfSLBfRwuiyO 40 | IB0I/vHliuT9Asaoe2K+IlZDcRwMjWFLcL5IKHRZlvy3dpqq2x6AsdoGbXi1ZdYG 41 | JVWkeyFPvglqCl/h+U0zrYWR1D9TzXmB3J5BXEzUuo5VRHarmNi9i8IV8TlNgyXn 42 | UlNJoofc9fKZylqwDt8NyqUosKR8xfJXtr/QCihy06bEC1ofE8lqG9+U+Xl4ZvyH 43 | YVRV7reWf1R4hePFdbGyEpQLJjwRJrP6HizgFM5PU6uS6S0hyHnwIdUl0ORjdLr7 44 | QEx8MWkCgYEA78Mk/7HyKG1+pVThkepmXazP0SA/GuaPUgiUf0crQRk27dgl+vQ8 45 | +VbJZ2ZV5P/75puabSTQfFlj2KBijXcKfavQjGcKCcRD12oe3cDSc4x2JpzQCNz/ 46 | 0x5/OlZNNcx43f5qgO+11J5Z+v58l4YSOfNJ7HfONSY1W+bAtt7FlcUCgYEA7sy0 47 | kimypNaJd62ukJz4B0UGsvCGgvYuM/7YB4UyVjLpTu4qaCJI+wy7nyIJC9rJlqKt 48 | AjqmEz1w2yb5KmbvHn161+cEJ4uoijJ2E6i00Z8KePi4M2ws3TD3HWnGpTt5rxDy 49 | CSpj92Yjr/nQ/32RW6N+gUXrLpMSwp8XvVv9EvMCgYEA4ShokXshhxe0jDzXDHmM 50 | okHMc36N5IxKYWZPVeuW0i6Ep/2JRU+iByGaR/ERjtlaTSkpb3/YDj7ABkov4tu8 51 | zWHRmliVU7CtaRluXR9cQ0jQF9jBgOFRmYiVQEqVfYVEqGzoxabXIhGHPK9Kf91X 52 | NnajoF6uFrmH+IMNzW4NLWUCgYAy6fhR9Yv+MzOqDaDbemwzeJceDcRQJdbiBSLg 53 | L5j04fP2fTcTbsPqquNR4XrWSTaT5GlIwWJpVb87KosTbFDtSkmnwLyVBeTQWkPs 54 | mxq6WtNryXPUmurR2j/FyKiu0Ah4t/8yzxPzSpavTW8vGgGk7S3quBKVoovsbOkt 55 | 2XAS2wKBgCFItSkGCyRuryHXm+ZK5/pwXcp7oldiZUeAWVhsNtl/n5fLOILfJkj4 56 | Jn7kifnwCW+kVLlaXeNDrH3Y0/sxNeUUtMI70N/9940I5lDBei34zzNKLEYT6Dt1 57 | gIXT3xZ1yV021bpkfnY/qMJClyQIPi1OhkKRpHvgPO49C6QT+HX6 58 | -----END RSA PRIVATE KEY----- -------------------------------------------------------------------------------- /jwt-resource-server/src/main/java/com/cheng/resource/ResourceServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.cheng.resource; 2 | 3 | import org.apache.catalina.filters.RequestDumperFilter; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Profile; 8 | import org.springframework.http.HttpMethod; 9 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 10 | import org.springframework.security.config.http.SessionCreationPolicy; 11 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; 12 | import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; 13 | import org.springframework.web.bind.annotation.RequestBody; 14 | import org.springframework.web.bind.annotation.RequestMapping; 15 | import org.springframework.web.bind.annotation.RequestMethod; 16 | import org.springframework.web.bind.annotation.RestController; 17 | 18 | import java.security.Principal; 19 | import java.time.LocalDateTime; 20 | import java.util.Collections; 21 | import java.util.LinkedList; 22 | import java.util.List; 23 | 24 | /** 25 | * @author fengcheng 26 | * @version 2017/8/26 27 | */ 28 | @SpringBootApplication 29 | @EnableResourceServer 30 | @RestController 31 | public class ResourceServerApplication extends ResourceServerConfigurerAdapter { 32 | 33 | public static void main(String[] args) { 34 | SpringApplication.run(ResourceServerApplication.class, args); 35 | } 36 | 37 | final List messages = Collections.synchronizedList(new LinkedList<>()); 38 | 39 | @RequestMapping(path = "api/messages", method = RequestMethod.GET) 40 | List getMessages(Principal principal) { 41 | return messages; 42 | } 43 | 44 | @RequestMapping(path = "api/messages", method = RequestMethod.POST) 45 | Message postMessage(Principal principal, @RequestBody Message message) { 46 | message.username = principal.getName(); 47 | message.createdAt = LocalDateTime.now(); 48 | messages.add(0, message); 49 | return message; 50 | } 51 | 52 | public static class Message { 53 | public String text; 54 | public String username; 55 | public LocalDateTime createdAt; 56 | } 57 | 58 | @Override 59 | public void configure(HttpSecurity http) throws Exception { 60 | http 61 | .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) 62 | .and() 63 | .authorizeRequests() 64 | .antMatchers(HttpMethod.GET, "/api/**").access("#oauth2.hasScope('read')") 65 | .antMatchers(HttpMethod.POST, "/api/**").access("#oauth2.hasScope('write')"); 66 | } 67 | 68 | @Profile("!cloud") 69 | @Bean 70 | RequestDumperFilter requestDumperFilter() { 71 | return new RequestDumperFilter(); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /resource-server/src/main/java/com/cheng/resource/ResourceServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.cheng.resource; 2 | 3 | import org.apache.catalina.filters.RequestDumperFilter; 4 | import org.springframework.boot.SpringApplication; 5 | import org.springframework.boot.autoconfigure.SpringBootApplication; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Profile; 8 | import org.springframework.http.HttpMethod; 9 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 10 | import org.springframework.security.config.http.SessionCreationPolicy; 11 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; 12 | import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; 13 | import org.springframework.web.bind.annotation.RequestBody; 14 | import org.springframework.web.bind.annotation.RequestMapping; 15 | import org.springframework.web.bind.annotation.RequestMethod; 16 | import org.springframework.web.bind.annotation.RestController; 17 | 18 | import java.security.Principal; 19 | import java.time.LocalDateTime; 20 | import java.util.Collections; 21 | import java.util.LinkedList; 22 | import java.util.List; 23 | 24 | /** 25 | * @author fengcheng 26 | * @version 2017/8/26 27 | */ 28 | @SpringBootApplication 29 | @EnableResourceServer 30 | @RestController 31 | public class ResourceServerApplication extends ResourceServerConfigurerAdapter { 32 | 33 | public static void main(String[] args) { 34 | SpringApplication.run(ResourceServerApplication.class, args); 35 | } 36 | 37 | final List messages = Collections.synchronizedList(new LinkedList<>()); 38 | 39 | @RequestMapping(path = "api/messages", method = RequestMethod.GET) 40 | List getMessages(Principal principal) { 41 | return messages; 42 | } 43 | 44 | @RequestMapping(path = "api/messages", method = RequestMethod.POST) 45 | Message postMessage(Principal principal, @RequestBody Message message) { 46 | message.username = principal.getName(); 47 | message.createdAt = LocalDateTime.now(); 48 | messages.add(0, message); 49 | return message; 50 | } 51 | 52 | public static class Message { 53 | public String text; 54 | public String username; 55 | public LocalDateTime createdAt; 56 | } 57 | 58 | @Override 59 | public void configure(HttpSecurity http) throws Exception { 60 | http 61 | .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) 62 | .and() 63 | .authorizeRequests() 64 | .antMatchers(HttpMethod.GET, "/api/**").access("#oauth2.hasScope('read')") 65 | .antMatchers(HttpMethod.POST, "/api/**").access("#oauth2.hasScope('write')"); 66 | } 67 | 68 | @Profile("!cloud") 69 | @Bean 70 | RequestDumperFilter requestDumperFilter() { 71 | return new RequestDumperFilter(); 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /ui/src/main/java/com/cheng/ui/UiApplication.java: -------------------------------------------------------------------------------- 1 | package com.cheng.ui; 2 | 3 | import org.apache.catalina.filters.RequestDumperFilter; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.beans.factory.annotation.Value; 6 | import org.springframework.boot.SpringApplication; 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; 8 | import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso; 9 | import org.springframework.context.annotation.Bean; 10 | import org.springframework.context.annotation.Profile; 11 | import org.springframework.http.RequestEntity; 12 | import org.springframework.security.oauth2.client.OAuth2ClientContext; 13 | import org.springframework.security.oauth2.client.OAuth2RestTemplate; 14 | import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails; 15 | import org.springframework.stereotype.Controller; 16 | import org.springframework.ui.Model; 17 | import org.springframework.web.bind.annotation.RequestMapping; 18 | import org.springframework.web.bind.annotation.RequestMethod; 19 | import org.springframework.web.bind.annotation.RequestParam; 20 | import org.springframework.web.util.UriComponentsBuilder; 21 | 22 | import java.time.LocalDateTime; 23 | import java.util.Arrays; 24 | import java.util.List; 25 | 26 | /** 27 | * @author fengcheng 28 | * @version 2017/8/26 29 | */ 30 | @SpringBootApplication 31 | @EnableOAuth2Sso 32 | public class UiApplication { 33 | 34 | public static void main(String[] args) { 35 | SpringApplication.run(UiApplication.class, args); 36 | } 37 | 38 | @Controller 39 | static class HomeController { 40 | @Autowired 41 | OAuth2RestTemplate restTemplate; 42 | @Value("${messages.url:http://localhost:9992}/api") 43 | String messagesUrl; 44 | 45 | @RequestMapping("/") 46 | String home(Model model) { 47 | List messages = Arrays.asList(restTemplate.getForObject(messagesUrl + "/messages", Message[].class)); 48 | model.addAttribute("messages", messages); 49 | return "index"; 50 | } 51 | 52 | @RequestMapping(path = "messages", method = RequestMethod.POST) 53 | String postMessages(@RequestParam String text) { 54 | Message message = new Message(); 55 | message.text = text; 56 | restTemplate.exchange(RequestEntity 57 | .post(UriComponentsBuilder.fromHttpUrl(messagesUrl).pathSegment("messages").build().toUri()) 58 | .body(message), Message.class); 59 | return "redirect:/"; 60 | } 61 | } 62 | 63 | public static class Message { 64 | public String text; 65 | public String username; 66 | public LocalDateTime createdAt; 67 | } 68 | 69 | @Profile("!cloud") 70 | @Bean 71 | RequestDumperFilter requestDumperFilter() { 72 | return new RequestDumperFilter(); 73 | } 74 | 75 | @Bean 76 | OAuth2RestTemplate oauth2RestTemplate(OAuth2ClientContext oauth2ClientContext, OAuth2ProtectedResourceDetails details) { 77 | return new OAuth2RestTemplate(details, oauth2ClientContext); 78 | } 79 | 80 | } 81 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | com.cheng 8 | oauth2-sso 9 | pom 10 | 1.0-SNAPSHOT 11 | 12 | auth-server 13 | resource-server 14 | ui 15 | jwt-auth-server 16 | jwt-resource-server 17 | 18 | 19 | 20 | 21 | aliyun-repos 22 | aliyun Repository 23 | http://maven.aliyun.com/nexus/content/groups/public 24 | 25 | 26 | 27 | 28 | aliyun-repos 29 | aliyun Repository 30 | http://maven.aliyun.com/nexus/content/groups/public 31 | 32 | 33 | 34 | 35 | org.springframework.boot 36 | spring-boot-starter-parent 37 | 1.5.6.RELEASE 38 | 39 | 40 | 41 | 42 | 43 | org.springframework.cloud 44 | spring-cloud-dependencies 45 | Camden.SR6 46 | pom 47 | import 48 | 49 | 50 | 51 | 52 | 1.8 53 | UTF-8 54 | 55 | 56 | 57 | 58 | 59 | org.springframework.boot 60 | spring-boot-maven-plugin 61 | 62 | 63 | org.springframework 64 | springloaded 65 | 1.2.6.RELEASE 66 | 67 | 68 | 69 | 70 | 71 | 72 | src/main/java 73 | 74 | **/*.xml 75 | 76 | true 77 | 78 | 79 | src/main/resources 80 | true 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /jwt-auth-server/src/main/java/com/cheng/auth/AuthServerApplication.java: -------------------------------------------------------------------------------- 1 | package com.cheng.auth; 2 | 3 | import org.apache.catalina.filters.RequestDumperFilter; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.boot.SpringApplication; 6 | import org.springframework.boot.autoconfigure.SpringBootApplication; 7 | import org.springframework.boot.autoconfigure.security.oauth2.authserver.AuthorizationServerProperties; 8 | import org.springframework.boot.context.properties.ConfigurationProperties; 9 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 10 | import org.springframework.context.annotation.Bean; 11 | import org.springframework.context.annotation.Configuration; 12 | import org.springframework.context.annotation.Profile; 13 | import org.springframework.core.annotation.Order; 14 | import org.springframework.security.authentication.AuthenticationManager; 15 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 16 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; 17 | import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; 18 | import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; 19 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; 20 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; 21 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; 22 | import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; 23 | import org.springframework.web.bind.annotation.RestController; 24 | import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; 25 | import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; 26 | 27 | import java.util.concurrent.TimeUnit; 28 | 29 | /** 30 | * @author fengcheng 31 | * @version 2017/8/24 32 | */ 33 | @SpringBootApplication 34 | @RestController 35 | public class AuthServerApplication { 36 | 37 | public static void main(String[] args) { 38 | SpringApplication.run(AuthServerApplication.class, args); 39 | } 40 | 41 | @Configuration 42 | static class MvcConfig extends WebMvcConfigurerAdapter { 43 | @Override 44 | public void addViewControllers(ViewControllerRegistry registry) { 45 | registry.addViewController("login").setViewName("login"); 46 | registry.addViewController("/").setViewName("index"); 47 | } 48 | } 49 | 50 | @Configuration 51 | @EnableAuthorizationServer 52 | @EnableConfigurationProperties({AuthorizationServerProperties.class}) 53 | static class OAuth2AuthorizationConfig extends AuthorizationServerConfigurerAdapter { 54 | @Autowired 55 | AuthenticationManager authenticationManager; 56 | @Autowired 57 | AuthorizationServerProperties authorizationServerProperties; 58 | 59 | @Override 60 | public void configure(ClientDetailsServiceConfigurer clients) throws Exception { 61 | clients.inMemory() 62 | .withClient("demo") 63 | .secret("demo") 64 | .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit") 65 | .scopes("read", "write") 66 | .accessTokenValiditySeconds((int) TimeUnit.HOURS.toSeconds(1)) 67 | .autoApprove(true); 68 | } 69 | 70 | @Override 71 | public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { 72 | endpoints.authenticationManager(authenticationManager).accessTokenConverter(jwtAccessTokenConverter()); 73 | } 74 | 75 | @Override 76 | public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { 77 | security.tokenKeyAccess(authorizationServerProperties.getTokenKeyAccess()); 78 | } 79 | 80 | @Bean 81 | @ConfigurationProperties("jwt") 82 | JwtAccessTokenConverter jwtAccessTokenConverter() { 83 | return new JwtAccessTokenConverter(); 84 | } 85 | } 86 | 87 | @Configuration 88 | @Order(-20) 89 | static class LoginConfig extends WebSecurityConfigurerAdapter { 90 | @Override 91 | protected void configure(HttpSecurity http) throws Exception { 92 | http 93 | .formLogin().loginPage("/login").permitAll() 94 | .and() 95 | .requestMatchers() 96 | .antMatchers("/", "/login", "/oauth/authorize", "/oauth/confirm_access") 97 | .and() 98 | .authorizeRequests() 99 | .anyRequest().authenticated(); 100 | } 101 | } 102 | 103 | @Profile("!cloud") 104 | @Bean 105 | RequestDumperFilter requestDumperFilter() { 106 | return new RequestDumperFilter(); 107 | } 108 | } 109 | --------------------------------------------------------------------------------