├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── docker-compose.yml ├── pom.xml └── src ├── main ├── java │ └── com │ │ └── blueskykong │ │ └── auth │ │ ├── AuthApplication.java │ │ ├── config │ │ ├── JerseyConfig.java │ │ ├── ServiceConfig.java │ │ └── oauth │ │ │ ├── OAuth2Config.java │ │ │ ├── ResourceServerConfig.java │ │ │ └── WebSecurityConfig.java │ │ ├── dao │ │ ├── ClientSecretDAO.java │ │ ├── PermissionDAO.java │ │ ├── RoleDAO.java │ │ ├── RolePermissionDAO.java │ │ ├── UserAccessDAO.java │ │ ├── UserRoleDAO.java │ │ ├── impl │ │ │ ├── MybatisClientSecretDAO.java │ │ │ ├── MybatisPermissionDAO.java │ │ │ ├── MybatisRoleDAO.java │ │ │ ├── MybatisRolePermissionDAO.java │ │ │ ├── MybatisURoleDAO.java │ │ │ └── MybatisUserAccessDAO.java │ │ ├── mapper │ │ │ ├── ClientSecretMapper.java │ │ │ ├── PermissionMapper.java │ │ │ ├── RoleMapper.java │ │ │ ├── RolePermissionMapper.java │ │ │ ├── UserAccessMapper.java │ │ │ └── UserRoleMapper.java │ │ └── typehandler │ │ │ └── UuidTypeHandler.java │ │ ├── dto │ │ ├── ApiClientDTO.java │ │ ├── DefaultRole.java │ │ ├── DefaultRoles.java │ │ ├── RolePermissionDTO.java │ │ └── UserRoleDTO.java │ │ ├── entity │ │ ├── BaseEntity.java │ │ ├── ClientSecret.java │ │ ├── ClientSecretStatus.java │ │ ├── Permission.java │ │ ├── Role.java │ │ ├── RolePermission.java │ │ ├── UserAccess.java │ │ └── UserRole.java │ │ ├── exception │ │ ├── AbstractException.java │ │ ├── CustomWebResponseExceptionTranslator.java │ │ ├── ErrorCode.java │ │ ├── ErrorCodes.java │ │ └── GenericErrorCodes.java │ │ ├── properties │ │ └── RedisProperties.java │ │ ├── rest │ │ ├── ClientSecretResource.java │ │ ├── SecurityResource.java │ │ └── UserRoleResource.java │ │ ├── security │ │ ├── CodeAuthenticationProvider.java │ │ ├── CustomAuthenticationProvider.java │ │ ├── CustomAuthenticationToken.java │ │ ├── CustomAuthorizationTokenServices.java │ │ ├── CustomCheckPermission.java │ │ ├── CustomRedisTokenStore.java │ │ ├── CustomTokenEnhancer.java │ │ ├── CustomUserDetails.java │ │ └── filter │ │ │ ├── CustomLogoutHandler.java │ │ │ ├── CustomSecurityFilter.java │ │ │ ├── SecureResourceFilterInvocationDefinitionSource.java │ │ │ └── SecurityAccessDecisionManager.java │ │ ├── service │ │ ├── ClientSecretService.java │ │ └── SecurityService.java │ │ └── utils │ │ ├── JsonUtil.java │ │ └── TimestampAdapter.java └── resources │ ├── application.yml │ ├── bootstrap.yml │ ├── conf │ └── generatorConfig.xml │ ├── db │ └── V1.0__Base_version.sql │ └── mybatis │ ├── config.xml │ └── mapper │ ├── ClientSecretMapper.xml │ ├── PermissionMapper.xml │ ├── RoleMapper.xml │ ├── RolePermissionMapper.xml │ ├── UserAccessMapper.xml │ └── UserRoleMapper.xml └── test ├── java └── com │ └── blueskykong │ └── auth │ ├── AuthApplicationTest.java │ └── config │ ├── BaseServiceTest.java │ ├── CustomContextInitializer.java │ └── TestJdbcConfig.java └── resources └── application-test.yml /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Config Files 4 | .classpath 5 | *.MF 6 | *.project 7 | .settings 8 | .tern-project 9 | 10 | # Mobile Tools for Java (J2ME) 11 | .mtj.tmp/ 12 | 13 | # Package Files # 14 | *.jar 15 | *.war 16 | *.ear 17 | 18 | checkstyle/ 19 | target/ 20 | *.iml 21 | auditlog/ 22 | .idea/ 23 | .DS_Store 24 | tmp.* 25 | 26 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 27 | hs_err_pid* 28 | /src/main/resources/*.yml 29 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | jdk: 3 | - openjdk8 -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 aoho 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/keets2012/Auth-service.svg?branch=master)](https://travis-ci.org/keets2012/Auth-service) 2 | [![codebeat badge](https://codebeat.co/badges/4594f615-67af-46b0-9adf-b69b476dc250)](https://codebeat.co/projects/github-com-keets2012-auth-service-master) 3 | ![](https://img.shields.io/badge/license-MIT-000000.svg) 4 | 5 | ## change logs 6 | 7 | - 2018.9.1 8 | 9 | 版本升到`2.0-SNAPSHOT`,欲使用`sb1.5.x`版本,请切换到TAG `1.0-RELEASE`。by [CANGWU](https://github.com/CANGWU) 10 | 11 | Spring Cloud Security 升级到`Finchley.RELEASE`,Spring Boot由1.5.X升级到2.0.X。 12 | 13 | ```xml 14 | 15 | org.springframework.cloud 16 | spring-cloud-dependencies 17 | Finchley.RELEASE 18 | 19 | ``` 20 | 21 | ```xml 22 | 23 | org.springframework.boot 24 | spring-boot-starter-parent 25 | 2.0.0.RELEASE 26 | 27 | ``` 28 | 29 | ## quick start 30 | 本次对项目结构进行了更新,token的存储机制基于redis,当然存储方式可以自由切换,Spring Security提供了SPI的多种实现。 31 | 32 | 客户端的信息还是基于jdbc实现,所以需要导入项目中提供的表`oauth_client_details` 。 33 | 34 | 推荐首先阅读专栏文章:[认证鉴权与API权限控制在微服务架构中的设计与实现](http://blueskykong.com/categories/Security/) 35 | 36 | **单独的整合项目地址为: 37 | GitHub:https://github.com/keets2012/microservice-integration 38 | 或者 码云:https://gitee.com/keets/microservice-integration** 39 | 40 | ### maintainer 41 | - keets2012 42 | - CANGWU 43 | 44 | ### password模式 45 | 项目克隆之后: 46 | 47 | 1. ~~安装一下,`mvn clean install`~~ 48 | 2. 修改Auth项目中的配置文件,写了`XXXX`的地方,替换成自己的实际地址(redis和mysql) 49 | 3. 数据库导入,sql脚本在项目中。创建auth数据库,运行auth.sql 50 | 4. `mvn clean spring-boot:run` 51 | 5. 其他细节参考博客 52 | 6. **你的star是对我最好的鼓励^_^** 53 | 54 | 进行请求获取Token授权: 55 | ![head](http://image.blueskykong.com/login1-header1.png "头部信息") 56 | ![form](http://image.blueskykong.com/loginform3.png "表单信息") 57 | 58 | 59 | 笔者自己运行了结果如下: 60 | 61 | ```yaml 62 | { 63 | "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1MDkwNzMzMjcsIlgtQU9ITy1Vc2VySWQiOiIxNGY1MmE0OS0yYTgxLTRhMmYtOGI5Mi01ZmU0NzUzZGRmZGEiLCJ1c2VyX25hbWUiOiIxODM2MjkxNjcyNiIsImp0aSI6IjM5NDEzN2I5LTNjZGItNGUyNy04NGRjLWM5YjEyYzk3ZTA4YyIsImNsaWVudF9pZCI6ImZyb250ZW5kIiwic2NvcGUiOlsiYWxsIl19.pGZhGNVECg0b4LB_pYXTTVKjNn8FA5biM04Bhcd-MEE", 64 | "token_type": "bearer", 65 | "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiIxODM2MjkxNjcyNiIsInNjb3BlIjpbImFsbCJdLCJhdGkiOiIzOTQxMzdiOS0zY2RiLTRlMjctODRkYy1jOWIxMmM5N2UwOGMiLCJleHAiOjE1MTE2MjIxMjcsIlgtQU9ITy1Vc2VySWQiOiIxNGY1MmE0OS0yYTgxLTRhMmYtOGI5Mi01ZmU0NzUzZGRmZGEiLCJqdGkiOiJkYTBmOTMxMS1lZjc0LTRiMjQtODViZi04ZTNjNDVhNGEyNzkiLCJjbGllbnRfaWQiOiJmcm9udGVuZCJ9.2MRdqEogAwbesRfj2TKoWhMazItBlpjbQx7dlgfFpHE", 66 | "expires_in": 43199, 67 | "scope": "all", 68 | "X-AOHO-UserId": "14f52a49-2a81-4a2f-8b92-5fe4753ddfda", 69 | "jti": "394137b9-3cdb-4e27-84dc-c9b12c97e08c", 70 | "X-AOHO-ClientId": "frontend" 71 | } 72 | ``` 73 | 74 | ps: 登录的用户名密码要在表单里面写,内容随意,因为在代码中已经去掉了对user服务的校验。 75 | 76 | ### 授权码模式 77 | 本次更新添加了对授权码模式的使用 78 | 79 | 授权码模式需要用户登录,所以借助浏览器 80 | 81 | 首先给数据库表中的`oauth_client_details`表中`client_id`为`frontend`的行`authorized_grant_types`添加`authorization_code`,`web_server_redirect_uri`设置为`http://localhost:8080`。表示该客户端允许授权码模式以及授权码回调地址为http://localhost:8080 82 | 83 | 浏览器访问地址 84 | 85 | ```yaml 86 | http://localhost:9000/oauth/authorize?response_type=code&client_id=frontend& 87 | scope=all&redirect_uri=http://localhost:8080 88 | ``` 89 | 90 | 91 | 进入登录授权页面并同意授权,从回调地址中获取授权码 92 | 93 | ```yaml 94 | http://localhost:8080/?code=xGjrTm 95 | ``` 96 | 97 | 通过授权码获取access_token 98 | 99 | ```yaml 100 | method: post 101 | url: http://localhost:9000/oauth/token?grant_type=authorization_code 102 | header: 103 | { 104 |  Authorization: Basic ZnJvbnRlbmQ6ZnJvbnRlbmQ=, 105 | Content-Type: application/x-www-form-urlencoded 106 | } 107 | body: 108 | { 109 | code: xGjrTm, 110 |  redirect_uri: http://localhost:8080 111 | } 112 | ``` 113 | 114 | ### 写在最后 115 | 116 | 项目整合如果遇到问题,可以加入qq群(649932629)交流。 117 | 118 | ![](http://image.blueskykong.com/qq-chat1.JPG) 119 | 120 | ps: qq交流群已设置付费,可以过滤很多广告,营造高质量的技术交流群。 121 | 122 | *有问题联系 aoho002#gmail.com* 123 | 124 | ### MIT License 125 | 126 | Copyright (c) 2018 aoho 127 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | mysql-auth: 2 | restart: always 3 | image: mysql:5.7 4 | ports: 5 | - "3306:3306" 6 | environment: 7 | - MYSQL_ROOT_PASSWORD=_123456_ 8 | - MYSQL_DATABASE=auth 9 | 10 | redis: 11 | container_name: auth-redis 12 | image: 'redis:4' 13 | ports: 14 | - '6379:6379' -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | Auth-Service 8 | com.blueskykong 9 | 2.0-SNAPSHOT 10 | jar 11 | 12 | OAuth Service 13 | 14 | 15 | org.springframework.boot 16 | spring-boot-starter-parent 17 | 2.0.4.RELEASE 18 | 19 | 20 | 21 | UTF-8 22 | UTF-8 23 | 1.8 24 | false 25 | 1.3.0 26 | 2.5.3 27 | 2.2.0 28 | 1.85 29 | 30 | 31 | 32 | 33 | org.springframework.boot 34 | spring-boot-starter-data-redis 35 | 36 | 37 | 38 | org.mybatis.spring.boot 39 | mybatis-spring-boot-starter 40 | ${mybatis.spring.version} 41 | 42 | 43 | 44 | org.projectlombok 45 | lombok 46 | provided 47 | 48 | 49 | 50 | org.springframework.cloud 51 | spring-cloud-starter-netflix-hystrix 52 | 53 | 54 | 55 | org.springframework.boot 56 | spring-boot-starter-actuator 57 | 58 | 59 | 60 | com.auth0 61 | java-jwt 62 | ${jwt.version} 63 | 64 | 65 | org.springframework.cloud 66 | spring-cloud-starter-security 67 | 68 | 69 | org.springframework.cloud 70 | spring-cloud-security 71 | 72 | 73 | org.springframework.boot 74 | spring-boot-starter-web 75 | 76 | 77 | 78 | org.springframework.boot 79 | spring-boot-starter-jersey 80 | 81 | 82 | 83 | 84 | mysql 85 | mysql-connector-java 86 | 87 | 88 | 89 | org.springframework.boot 90 | spring-boot-starter-jdbc 91 | 92 | 93 | 94 | org.springframework.boot 95 | spring-boot-starter-test 96 | test 97 | 98 | 99 | 100 | org.springframework 101 | spring-aspects 102 | compile 103 | 104 | 105 | 106 | org.dbunit 107 | dbunit 108 | ${dbunit.version} 109 | test 110 | 111 | 112 | 113 | org.flywaydb 114 | flyway-core 115 | 116 | 117 | 118 | org.apache.commons 119 | commons-lang3 120 | 3.5 121 | 122 | 123 | net.sf.oval 124 | oval 125 | ${oval.version} 126 | 127 | 128 | 129 | io.jsonwebtoken 130 | jjwt 131 | 0.6.0 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | org.springframework.cloud 140 | spring-cloud-dependencies 141 | Finchley.RELEASE 142 | pom 143 | import 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | org.springframework.boot 153 | spring-boot-maven-plugin 154 | 155 | 156 | 157 | 158 | 159 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/AuthApplication.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | 6 | @SpringBootApplication 7 | public class AuthApplication { 8 | 9 | public static void main(String[] args) { 10 | SpringApplication.run(AuthApplication.class, args); 11 | } 12 | 13 | } -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/config/JerseyConfig.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.config; 2 | 3 | 4 | import com.blueskykong.auth.rest.ClientSecretResource; 5 | import com.blueskykong.auth.rest.SecurityResource; 6 | import com.blueskykong.auth.rest.UserRoleResource; 7 | import org.glassfish.jersey.server.ResourceConfig; 8 | import org.glassfish.jersey.server.spring.scope.RequestContextFilter; 9 | import org.springframework.stereotype.Component; 10 | 11 | import javax.ws.rs.ApplicationPath; 12 | 13 | 14 | @Component 15 | @ApplicationPath("api") 16 | public class JerseyConfig extends ResourceConfig { 17 | public JerseyConfig() { 18 | register(RequestContextFilter.class); 19 | register(ClientSecretResource.class); 20 | //配置restful package. 21 | register(SecurityResource.class); 22 | register(UserRoleResource.class); 23 | } 24 | } -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/config/ServiceConfig.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.config; 2 | 3 | import com.blueskykong.auth.exception.CustomWebResponseExceptionTranslator; 4 | import org.mybatis.spring.annotation.MapperScan; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; 8 | 9 | 10 | @Configuration 11 | public class ServiceConfig { 12 | 13 | @Bean 14 | public WebResponseExceptionTranslator webResponseExceptionTranslator() { 15 | return new CustomWebResponseExceptionTranslator(); 16 | } 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/config/oauth/OAuth2Config.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.config.oauth; 2 | 3 | import com.blueskykong.auth.security.CustomAuthorizationTokenServices; 4 | import com.blueskykong.auth.security.CustomRedisTokenStore; 5 | import com.blueskykong.auth.security.CustomTokenEnhancer; 6 | import com.blueskykong.auth.service.ClientSecretService; 7 | import com.zaxxer.hikari.HikariDataSource; 8 | import org.mybatis.spring.annotation.MapperScan; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; 11 | import org.springframework.context.annotation.AdviceMode; 12 | import org.springframework.context.annotation.Bean; 13 | import org.springframework.context.annotation.Configuration; 14 | import org.springframework.context.annotation.Lazy; 15 | import org.springframework.core.annotation.Order; 16 | import org.springframework.data.redis.connection.RedisConnectionFactory; 17 | import org.springframework.data.redis.core.RedisTemplate; 18 | import org.springframework.data.redis.core.StringRedisTemplate; 19 | import org.springframework.security.authentication.AuthenticationManager; 20 | import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer; 21 | import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter; 22 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; 23 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; 24 | import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer; 25 | import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService; 26 | import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator; 27 | import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; 28 | import org.springframework.security.oauth2.provider.token.TokenStore; 29 | import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; 30 | import org.springframework.transaction.annotation.EnableTransactionManagement; 31 | 32 | import javax.sql.DataSource; 33 | import java.net.UnknownHostException; 34 | 35 | @Configuration 36 | @EnableAuthorizationServer 37 | public class OAuth2Config extends AuthorizationServerConfigurerAdapter { 38 | 39 | 40 | private AuthenticationManager authenticationManager; 41 | 42 | private WebResponseExceptionTranslator webResponseExceptionTranslator; 43 | 44 | private DataSource dataSource; 45 | 46 | private RedisConnectionFactory redisConnectionFactory; 47 | 48 | @Autowired 49 | public OAuth2Config(AuthenticationManager authenticationManager, WebResponseExceptionTranslator webResponseExceptionTranslator, 50 | HikariDataSource dataSource, RedisConnectionFactory redisConnectionFactory) { 51 | this.authenticationManager = authenticationManager; 52 | this.webResponseExceptionTranslator = webResponseExceptionTranslator; 53 | this.dataSource = dataSource; 54 | this.redisConnectionFactory = redisConnectionFactory; 55 | } 56 | 57 | @Bean 58 | public TokenStore tokenStore(RedisConnectionFactory redisConnectionFactory) { 59 | return new CustomRedisTokenStore(redisConnectionFactory); 60 | } 61 | 62 | @Bean 63 | public JdbcClientDetailsService clientDetailsService() { 64 | return new JdbcClientDetailsService(dataSource); 65 | } 66 | 67 | @Override 68 | public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { 69 | //security.addTokenEndpointAuthenticationFilter(new CustomSecurityFilter()); 70 | security 71 | .tokenKeyAccess("permitAll()") 72 | .checkTokenAccess("isAuthenticated()"); 73 | } 74 | 75 | @Override 76 | public void configure(ClientDetailsServiceConfigurer clients) throws Exception { 77 | clients.withClientDetails(clientDetailsService()); 78 | } 79 | 80 | @Override 81 | public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { 82 | endpoints.authenticationManager(authenticationManager) 83 | .tokenStore(tokenStore(redisConnectionFactory)) 84 | .tokenServices(authorizationServerTokenServices()) 85 | .accessTokenConverter(accessTokenConverter()) 86 | .exceptionTranslator(webResponseExceptionTranslator); 87 | } 88 | 89 | @Bean 90 | public JwtAccessTokenConverter accessTokenConverter() { 91 | JwtAccessTokenConverter converter = new CustomTokenEnhancer(); 92 | converter.setSigningKey("secret"); 93 | return converter; 94 | } 95 | 96 | @Bean 97 | public AuthorizationServerTokenServices authorizationServerTokenServices() { 98 | CustomAuthorizationTokenServices customTokenServices = new CustomAuthorizationTokenServices(); 99 | customTokenServices.setTokenStore(tokenStore(redisConnectionFactory)); 100 | customTokenServices.setSupportRefreshToken(true); 101 | customTokenServices.setReuseRefreshToken(false); 102 | customTokenServices.setClientDetailsService(clientDetailsService()); 103 | customTokenServices.setTokenEnhancer(accessTokenConverter()); 104 | return customTokenServices; 105 | } 106 | 107 | @Configuration 108 | protected static class RedisConfiguration { 109 | 110 | @Bean 111 | @ConditionalOnMissingBean(name = "redisTemplate") 112 | public RedisTemplate redisTemplate( 113 | RedisConnectionFactory redisConnectionFactory) 114 | throws UnknownHostException { 115 | RedisTemplate template = new RedisTemplate(); 116 | template.setConnectionFactory(redisConnectionFactory); 117 | return template; 118 | } 119 | 120 | @Bean 121 | @ConditionalOnMissingBean(StringRedisTemplate.class) 122 | public StringRedisTemplate stringRedisTemplate( 123 | RedisConnectionFactory redisConnectionFactory) 124 | throws UnknownHostException { 125 | StringRedisTemplate template = new StringRedisTemplate(); 126 | template.setConnectionFactory(redisConnectionFactory); 127 | return template; 128 | } 129 | } 130 | 131 | @Configuration 132 | @EnableTransactionManagement(mode = AdviceMode.ASPECTJ) 133 | @MapperScan("com.blueskykong.auth.dao.mapper") 134 | public static class DatasourceConfig { 135 | 136 | 137 | } 138 | 139 | 140 | } 141 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/config/oauth/ResourceServerConfig.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.config.oauth; 2 | 3 | import com.blueskykong.auth.security.filter.CustomLogoutHandler; 4 | import com.blueskykong.auth.security.filter.CustomSecurityFilter; 5 | import org.springframework.context.annotation.Bean; 6 | import org.springframework.context.annotation.Configuration; 7 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; 8 | import org.springframework.security.config.http.SessionCreationPolicy; 9 | import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; 10 | import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; 11 | import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; 12 | import org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler; 13 | 14 | /** 15 | * @author keets 16 | * @date 2017/9/25 17 | */ 18 | @Configuration 19 | //@EnableResourceServer 20 | public class ResourceServerConfig extends ResourceServerConfigurerAdapter { 21 | // 22 | // @Override 23 | // public void configure(HttpSecurity http) throws Exception { 24 | // http.csrf().disable() 25 | // .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) 26 | // .and() 27 | // .requestMatchers().antMatchers("/**") 28 | // .and().authorizeRequests() 29 | // .antMatchers("/**").permitAll() 30 | // .anyRequest().authenticated() 31 | // .and().formLogin().permitAll() 32 | // .and().logout() 33 | // .logoutUrl("/logout") 34 | // .clearAuthentication(true) 35 | // .logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler()) 36 | // .addLogoutHandler(customLogoutHandler()); 37 | // 38 | // //http.antMatcher("/api/**").addFilterAt(customSecurityFilter(), FilterSecurityInterceptor.class); 39 | // 40 | // } 41 | 42 | /* @Bean 43 | public CustomSecurityFilter customSecurityFilter() { 44 | return new CustomSecurityFilter(); 45 | } 46 | */ 47 | 48 | 49 | 50 | @Override 51 | public void configure(ResourceServerSecurityConfigurer resources) throws Exception { 52 | super.configure(resources); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/config/oauth/WebSecurityConfig.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.config.oauth; 2 | 3 | import com.blueskykong.auth.security.CodeAuthenticationProvider; 4 | import com.blueskykong.auth.security.CustomAuthenticationProvider; 5 | import com.blueskykong.auth.security.filter.CustomLogoutHandler; 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.authentication.AuthenticationManager; 10 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; 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.crypto.password.NoOpPasswordEncoder; 16 | import org.springframework.security.crypto.password.PasswordEncoder; 17 | import org.springframework.security.crypto.scrypt.SCryptPasswordEncoder; 18 | import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; 19 | import org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler; 20 | 21 | /** 22 | * Created by xuan on 2018/1/3. 23 | */ 24 | @Configuration 25 | @EnableWebSecurity 26 | public class WebSecurityConfig extends WebSecurityConfigurerAdapter{ 27 | 28 | 29 | @Autowired 30 | CustomAuthenticationProvider customAuthenticationProvider; 31 | @Autowired 32 | CodeAuthenticationProvider codeAuthenticationProvider; 33 | 34 | @Override 35 | protected void configure(HttpSecurity http) throws Exception { 36 | 37 | 38 | http.csrf().disable() 39 | .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) 40 | .and() 41 | .requestMatchers().antMatchers("/**") 42 | .and().authorizeRequests() 43 | .antMatchers("/**").permitAll() 44 | .anyRequest().authenticated() 45 | .and().formLogin().permitAll() 46 | .and().logout() 47 | .logoutUrl("/logout") 48 | .logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler()) 49 | .addLogoutHandler(customLogoutHandler()); 50 | } 51 | 52 | 53 | @Bean 54 | public CustomLogoutHandler customLogoutHandler() { 55 | return new CustomLogoutHandler(); 56 | } 57 | 58 | 59 | 60 | @Override 61 | public void configure(AuthenticationManagerBuilder auth) { 62 | auth.authenticationProvider(customAuthenticationProvider); 63 | auth.authenticationProvider(codeAuthenticationProvider); 64 | } 65 | 66 | @Bean 67 | @Override 68 | public AuthenticationManager authenticationManagerBean() throws Exception { 69 | return super.authenticationManagerBean(); 70 | } 71 | 72 | @Bean 73 | public PasswordEncoder passwordEncoder(){ 74 | 75 | return new SCryptPasswordEncoder(); 76 | 77 | } 78 | 79 | 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/dao/ClientSecretDAO.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.dao; 2 | 3 | import com.blueskykong.auth.entity.ClientSecret; 4 | import com.blueskykong.auth.entity.ClientSecretStatus; 5 | import org.apache.ibatis.annotations.Mapper; 6 | 7 | import java.util.List; 8 | import java.util.UUID; 9 | 10 | 11 | @Mapper 12 | public interface ClientSecretDAO { 13 | int create(ClientSecret clientSecret); 14 | 15 | String getScope(String clientId,String clientSecret); 16 | 17 | List get(ClientSecret clientSecret); 18 | 19 | int updateStatusByTenantId(UUID tenantId, ClientSecretStatus status); 20 | 21 | int updateStatusByClientId(String clientId, ClientSecretStatus status); 22 | 23 | int update(ClientSecret clientSecret); 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/dao/PermissionDAO.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.dao; 2 | 3 | import com.blueskykong.auth.entity.Permission; 4 | 5 | import java.util.List; 6 | import java.util.Map; 7 | import java.util.UUID; 8 | 9 | /** 10 | * @author keets 11 | * @date 2017/11/22 12 | */ 13 | public interface PermissionDAO { 14 | 15 | int deleteById(UUID id); 16 | 17 | int insert(Permission record); 18 | 19 | Permission selectById(UUID id); 20 | 21 | void updateName(UUID id, String newName); 22 | 23 | List selectAll(); 24 | 25 | List getPermissionList(Map paramMap); 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/dao/RoleDAO.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.dao; 2 | 3 | import com.blueskykong.auth.entity.Role; 4 | 5 | import java.util.List; 6 | import java.util.UUID; 7 | 8 | /** 9 | * Created by keets on 2017/11/22. 10 | */ 11 | public interface RoleDAO { 12 | 13 | void insert(Role role); 14 | 15 | int deleteById(UUID id); 16 | 17 | void update(Role role); 18 | 19 | Role selectById(UUID id); 20 | 21 | List selectAll(); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/dao/RolePermissionDAO.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.dao; 2 | 3 | import com.blueskykong.auth.entity.RolePermission; 4 | 5 | import java.util.List; 6 | import java.util.UUID; 7 | 8 | /** 9 | * @author keets 10 | * @date 2017/11/22 11 | */ 12 | public interface RolePermissionDAO { 13 | 14 | int deleteById(Long id); 15 | 16 | Long insert(RolePermission record); 17 | 18 | List selectByRoleId(UUID roleId); 19 | 20 | int updateById(RolePermission record); 21 | 22 | void deleteByRoleIdAndPermissionId(UUID rId, UUID pId); 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/dao/UserAccessDAO.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.dao; 2 | 3 | 4 | import com.blueskykong.auth.entity.UserAccess; 5 | 6 | import java.util.List; 7 | import java.util.UUID; 8 | 9 | 10 | public interface UserAccessDAO { 11 | 12 | 13 | List securitySelectByUserId(UUID userId); 14 | 15 | List securitySelectByUserIdWithFakeDoc(UUID userId); 16 | 17 | int securityInsertRecord(UserAccess record); 18 | 19 | int securityUpdateRecord(UserAccess record); 20 | 21 | int deleteByUserId(UUID userId); 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/dao/UserRoleDAO.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.dao; 2 | 3 | 4 | import com.blueskykong.auth.dto.UserRoleDTO; 5 | import com.blueskykong.auth.entity.UserRole; 6 | 7 | import java.util.List; 8 | import java.util.UUID; 9 | 10 | 11 | public interface UserRoleDAO { 12 | 13 | Long insertUtRole(UserRole userRole); 14 | 15 | List selectByUserId(UUID userId); 16 | 17 | int updateById(UserRole record); 18 | 19 | 20 | int deleteByUserId(UUID userId); 21 | 22 | List selectUserRoleList(UUID userId); 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/dao/impl/MybatisClientSecretDAO.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.dao.impl; 2 | 3 | import com.blueskykong.auth.dao.ClientSecretDAO; 4 | import com.blueskykong.auth.dao.mapper.ClientSecretMapper; 5 | import com.blueskykong.auth.entity.ClientSecret; 6 | import com.blueskykong.auth.entity.ClientSecretStatus; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import java.util.HashMap; 11 | import java.util.List; 12 | import java.util.Map; 13 | import java.util.UUID; 14 | 15 | @Repository 16 | public class MybatisClientSecretDAO implements ClientSecretDAO { 17 | 18 | @Autowired 19 | private ClientSecretMapper mapper; 20 | 21 | @Override 22 | public int create(ClientSecret clientSecret) { 23 | return mapper.insert(clientSecret); 24 | } 25 | 26 | @Override 27 | public String getScope(String clientId, String clientSecret) { 28 | return mapper.getScope(clientId,clientSecret); 29 | } 30 | 31 | @Override 32 | public List get(ClientSecret clientSecret) { 33 | Map params = new HashMap<>(); 34 | params.put("clientId", clientSecret.getClientId()); 35 | return mapper.selectByParams(params); 36 | } 37 | 38 | @Override 39 | public int updateStatusByTenantId(UUID tenantId, ClientSecretStatus status) { 40 | Map params = new HashMap<>(); 41 | params.put("tenantId", tenantId); 42 | params.put("status", status.toString()); 43 | 44 | return mapper.updateStatus(params); 45 | } 46 | 47 | @Override 48 | public int updateStatusByClientId(String clientId, ClientSecretStatus status) { 49 | Map params = new HashMap<>(); 50 | params.put("clientId", clientId); 51 | params.put("status", status.toString()); 52 | 53 | return mapper.updateStatus(params); 54 | } 55 | 56 | @Override 57 | public int update(ClientSecret clientSecret) { 58 | Map params = new HashMap<>(); 59 | params.put("clientId", clientSecret.getClientId()); 60 | params.put("clientSecret", clientSecret.getClientSecret()); 61 | params.put("tenantId", clientSecret.getTenantId()); 62 | params.put("purpose", clientSecret.getPurpose()); 63 | params.put("status", clientSecret.getStatus().toString()); 64 | 65 | return mapper.updateByParams(params); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/dao/impl/MybatisPermissionDAO.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.dao.impl; 2 | 3 | import com.blueskykong.auth.dao.PermissionDAO; 4 | import com.blueskykong.auth.dao.mapper.PermissionMapper; 5 | import com.blueskykong.auth.entity.Permission; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Repository; 8 | 9 | import java.util.List; 10 | import java.util.Map; 11 | import java.util.UUID; 12 | 13 | /** 14 | * @author keets 15 | * @date 2017/11/22 16 | */ 17 | @Repository 18 | public class MybatisPermissionDAO implements PermissionDAO { 19 | 20 | @Autowired 21 | private PermissionMapper permissionMapper; 22 | 23 | @Override 24 | public int deleteById(UUID id) { 25 | return permissionMapper.deleteById(id); 26 | } 27 | 28 | @Override 29 | public int insert(Permission record) { 30 | return permissionMapper.insert(record); 31 | } 32 | 33 | @Override 34 | public Permission selectById(UUID id) { 35 | return permissionMapper.selectById(id); 36 | } 37 | 38 | @Override 39 | public void updateName(UUID id, String name) { 40 | permissionMapper.updateName(id, name); 41 | } 42 | 43 | @Override 44 | public List selectAll() { 45 | return permissionMapper.selectAll(); 46 | } 47 | 48 | @Override 49 | public List getPermissionList(Map paramMap) { 50 | return permissionMapper.selectByMap(paramMap); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/dao/impl/MybatisRoleDAO.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.dao.impl; 2 | 3 | import com.blueskykong.auth.dao.RoleDAO; 4 | import com.blueskykong.auth.dao.mapper.RoleMapper; 5 | import com.blueskykong.auth.entity.Role; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Repository; 10 | 11 | import java.util.List; 12 | import java.util.UUID; 13 | 14 | /** 15 | * @author keets 16 | * @date 2017/11/22 17 | */ 18 | @Repository 19 | public class MybatisRoleDAO implements RoleDAO { 20 | 21 | @Autowired 22 | private RoleMapper roleMapper; 23 | 24 | private static final Logger LOGGER = LoggerFactory.getLogger(MybatisRoleDAO.class); 25 | 26 | @Override 27 | public void insert(Role role) { 28 | roleMapper.insert(role); 29 | } 30 | 31 | @Override 32 | public int deleteById(UUID id) { 33 | return roleMapper.deleteByPrimaryKey(id); 34 | } 35 | 36 | @Override 37 | public void update(Role role) { 38 | roleMapper.updateByPrimaryKey(role); 39 | } 40 | 41 | @Override 42 | public Role selectById(UUID id) { 43 | return roleMapper.selectByPrimaryKey(id); 44 | } 45 | 46 | @Override 47 | public List selectAll() { 48 | return roleMapper.selectAll(); 49 | } 50 | 51 | } 52 | 53 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/dao/impl/MybatisRolePermissionDAO.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.dao.impl; 2 | 3 | import com.blueskykong.auth.dao.RolePermissionDAO; 4 | import com.blueskykong.auth.dao.mapper.RolePermissionMapper; 5 | import com.blueskykong.auth.entity.RolePermission; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Component; 8 | 9 | import java.util.List; 10 | import java.util.UUID; 11 | 12 | /** 13 | * @author keets 14 | * @date 2017/11/22 15 | */ 16 | @Component 17 | public class MybatisRolePermissionDAO implements RolePermissionDAO { 18 | 19 | @Autowired 20 | private RolePermissionMapper rolePermissionMapper; 21 | 22 | @Override 23 | public int deleteById(Long id) { 24 | return rolePermissionMapper.deleteByPrimaryKey(id); 25 | } 26 | 27 | @Override 28 | public Long insert(RolePermission record) { 29 | rolePermissionMapper.insert(record); 30 | return record.getId(); 31 | } 32 | 33 | @Override 34 | public List selectByRoleId(UUID roleId) { 35 | return rolePermissionMapper.selectByRoleId(roleId); 36 | } 37 | 38 | @Override 39 | public int updateById(RolePermission record) { 40 | return rolePermissionMapper.updateByPrimaryKey(record); 41 | } 42 | 43 | @Override 44 | public void deleteByRoleIdAndPermissionId(UUID rId, UUID pId) { 45 | rolePermissionMapper.deleteByRoleIdAndPermissionId(rId, pId); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/dao/impl/MybatisURoleDAO.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.dao.impl; 2 | 3 | import com.blueskykong.auth.dao.UserRoleDAO; 4 | import com.blueskykong.auth.dao.mapper.UserRoleMapper; 5 | import com.blueskykong.auth.dto.UserRoleDTO; 6 | import com.blueskykong.auth.entity.UserRole; 7 | import org.springframework.beans.factory.annotation.Autowired; 8 | import org.springframework.stereotype.Repository; 9 | 10 | import java.util.HashMap; 11 | import java.util.List; 12 | import java.util.Map; 13 | import java.util.UUID; 14 | 15 | 16 | @Repository 17 | public class MybatisURoleDAO implements UserRoleDAO { 18 | 19 | @Autowired 20 | UserRoleMapper userRoleMapper; 21 | 22 | @Override 23 | public Long insertUtRole(UserRole UserRole) { 24 | userRoleMapper.insert(UserRole); 25 | return UserRole.getId(); 26 | } 27 | 28 | @Override 29 | public List selectByUserId(UUID userId) { 30 | return userRoleMapper.selectByUId(userId); 31 | } 32 | 33 | @Override 34 | public int updateById(UserRole record) { 35 | return userRoleMapper.updateByPrimaryKey(record); 36 | } 37 | 38 | @Override 39 | public int deleteByUserId(UUID userId) { 40 | Map map = new HashMap<>(); 41 | map.put("userId", userId); 42 | 43 | return userRoleMapper.deleteByUserId(userId); 44 | } 45 | 46 | @Override 47 | public List selectUserRoleList(UUID userId) { 48 | return userRoleMapper.selectUserRoleList(userId); 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/dao/impl/MybatisUserAccessDAO.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.dao.impl; 2 | 3 | import com.blueskykong.auth.dao.UserAccessDAO; 4 | import com.blueskykong.auth.dao.mapper.UserAccessMapper; 5 | import com.blueskykong.auth.entity.UserAccess; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.stereotype.Repository; 8 | 9 | import java.util.HashMap; 10 | import java.util.List; 11 | import java.util.Map; 12 | import java.util.UUID; 13 | 14 | @Repository 15 | public class MybatisUserAccessDAO implements UserAccessDAO { 16 | 17 | @Autowired 18 | UserAccessMapper userAccessMapper; 19 | 20 | @Override 21 | public List securitySelectByUserId(UUID userId) { 22 | return userAccessMapper.securitySelectByUserId(userId); 23 | } 24 | 25 | @Override 26 | public List securitySelectByUserIdWithFakeDoc(UUID userId) { 27 | return userAccessMapper.securitySelectByUserIdWithFakeDoc(userId); 28 | } 29 | 30 | @Override 31 | public int securityInsertRecord(UserAccess record) { 32 | return userAccessMapper.securityInsertRecord(record); 33 | } 34 | 35 | @Override 36 | public int securityUpdateRecord(UserAccess record) { 37 | return userAccessMapper.securityUpdateRecord(record); 38 | } 39 | 40 | @Override 41 | public int deleteByUserId(UUID userId) { 42 | Map map = new HashMap<>(); 43 | map.put("userId", userId); 44 | 45 | return userAccessMapper.deleteByUserId(userId); 46 | } 47 | 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/dao/mapper/ClientSecretMapper.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.dao.mapper; 2 | 3 | import com.blueskykong.auth.entity.ClientSecret; 4 | import org.apache.ibatis.annotations.Param; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | 9 | 10 | public interface ClientSecretMapper { 11 | 12 | String getScope(@Param("clientId")String clientId,@Param("clientSecret")String clientSecret); 13 | 14 | 15 | int insert(ClientSecret record); 16 | 17 | List selectByParams(Map map); 18 | 19 | int updateByParams(Map map); 20 | 21 | int updateStatus(Map map); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/dao/mapper/PermissionMapper.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.dao.mapper; 2 | 3 | import com.blueskykong.auth.entity.Permission; 4 | import org.apache.ibatis.annotations.Param; 5 | 6 | import java.util.List; 7 | import java.util.Map; 8 | import java.util.UUID; 9 | 10 | /** 11 | * Created by keets on 2017/11/22. 12 | */ 13 | public interface PermissionMapper { 14 | 15 | int deleteById(@Param("id") UUID id); 16 | 17 | int insert(Permission record); 18 | 19 | Permission selectById(@Param("id") UUID id); 20 | 21 | List selectAll(); 22 | 23 | int updateById(Permission record); 24 | 25 | void updateName(UUID id, String newName); 26 | 27 | List selectByMap(Map paraMap); 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/dao/mapper/RoleMapper.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.dao.mapper; 2 | 3 | import com.blueskykong.auth.entity.Role; 4 | import org.apache.ibatis.annotations.Param; 5 | 6 | import java.util.List; 7 | import java.util.UUID; 8 | 9 | 10 | public interface RoleMapper { 11 | 12 | int deleteByPrimaryKey(@Param("id") UUID id); 13 | 14 | int insert(Role record); 15 | 16 | Role selectByPrimaryKey(@Param("id") UUID id); 17 | 18 | int updateByPrimaryKey(Role record); 19 | 20 | List selectAll(); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/dao/mapper/RolePermissionMapper.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.dao.mapper; 2 | 3 | import com.blueskykong.auth.entity.RolePermission; 4 | import org.apache.ibatis.annotations.Param; 5 | 6 | import java.util.List; 7 | import java.util.UUID; 8 | 9 | 10 | public interface RolePermissionMapper { 11 | 12 | int deleteByPrimaryKey(Long id); 13 | 14 | Long insert(RolePermission record); 15 | 16 | List selectByRoleId(@Param("roleId") UUID roleId); 17 | 18 | int updateByPrimaryKey(RolePermission record); 19 | 20 | void deleteByRoleIdAndPermissionId(@Param("roleId") UUID roleId, @Param("permissionId") UUID permissionId); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/dao/mapper/UserAccessMapper.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.dao.mapper; 2 | 3 | import com.blueskykong.auth.entity.UserAccess; 4 | import org.apache.ibatis.annotations.Param; 5 | 6 | import java.util.List; 7 | import java.util.UUID; 8 | 9 | 10 | public interface UserAccessMapper { 11 | 12 | List securitySelectByUserId(@Param("userId") UUID userId); 13 | 14 | List securitySelectByUserIdWithFakeDoc(@Param("userId") UUID userId); 15 | 16 | int securityInsertRecord(UserAccess record); 17 | 18 | int securityUpdateRecord(UserAccess record); 19 | 20 | int deleteByUserId(@Param("userId") UUID userId); 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/dao/mapper/UserRoleMapper.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.dao.mapper; 2 | 3 | import com.blueskykong.auth.dto.UserRoleDTO; 4 | import com.blueskykong.auth.entity.UserRole; 5 | import org.apache.ibatis.annotations.Param; 6 | 7 | import java.util.List; 8 | import java.util.UUID; 9 | 10 | public interface UserRoleMapper { 11 | 12 | int deleteById(Long id); 13 | 14 | Long insert(UserRole record); 15 | 16 | List selectByUId(@Param("userId") UUID userId); 17 | 18 | int updateByPrimaryKey(UserRole record); 19 | 20 | int deleteByUserId(@Param("userId") UUID userId); 21 | 22 | List selectUserRoleList(@Param("userId") UUID userId); 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/dao/typehandler/UuidTypeHandler.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.dao.typehandler; 2 | 3 | import org.apache.ibatis.type.JdbcType; 4 | import org.apache.ibatis.type.TypeHandler; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.util.StringUtils; 8 | 9 | import java.sql.CallableStatement; 10 | import java.sql.PreparedStatement; 11 | import java.sql.ResultSet; 12 | import java.sql.SQLException; 13 | import java.sql.Types; 14 | import java.util.UUID; 15 | 16 | /** 17 | * Handler for UUID types. 18 | * 19 | * @see UUID 20 | */ 21 | public class UuidTypeHandler implements TypeHandler { 22 | private static final Logger LOG = LoggerFactory.getLogger(UuidTypeHandler.class); 23 | 24 | @Override 25 | public void setParameter(PreparedStatement ps, int i, UUID parameter, JdbcType jdbcType) throws SQLException { 26 | if (parameter == null) { 27 | ps.setObject(i, null, Types.VARCHAR); 28 | } else { 29 | ps.setObject(i, parameter.toString(), Types.VARCHAR); 30 | } 31 | 32 | } 33 | 34 | @Override 35 | public UUID getResult(ResultSet rs, String columnName) throws SQLException { 36 | return toUUID(rs.getString(columnName)); 37 | } 38 | 39 | @Override 40 | public UUID getResult(ResultSet rs, int columnIndex) throws SQLException { 41 | return toUUID(rs.getString(columnIndex)); 42 | } 43 | 44 | @Override 45 | public UUID getResult(CallableStatement cs, int columnIndex) throws SQLException { 46 | return toUUID(cs.getString(columnIndex)); 47 | } 48 | 49 | private static UUID toUUID(String val) throws SQLException { 50 | if (StringUtils.isEmpty(val)) { 51 | return null; 52 | } 53 | try { 54 | return UUID.fromString(val); 55 | } catch (IllegalArgumentException e) { 56 | LOG.warn("Bad UUID found: {}", val); 57 | } 58 | return null; 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/dto/ApiClientDTO.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.dto; 2 | 3 | import com.blueskykong.auth.exception.ErrorCodes; 4 | import net.sf.oval.constraint.NotBlank; 5 | 6 | import javax.validation.constraints.NotNull; 7 | import java.util.UUID; 8 | 9 | 10 | public class ApiClientDTO { 11 | 12 | @NotBlank(message = ErrorCodes.CLIENT_ID_IS_NULL_STR) 13 | @NotNull(message = ErrorCodes.CLIENT_ID_IS_NULL_STR) 14 | private String clientId; 15 | 16 | @NotBlank(message = ErrorCodes.CLIENT_SECRET_IS_NULL_STR) 17 | @NotNull(message = ErrorCodes.CLIENT_SECRET_IS_NULL_STR) 18 | private String clientSecret; 19 | 20 | private String status; 21 | 22 | private String purpose; 23 | 24 | @NotNull(message = ErrorCodes.ORGANIZAITON_ID_IS_NULL_STR) 25 | private UUID tenantId; 26 | 27 | private UUID userId; 28 | 29 | public String getClientId() { 30 | return clientId; 31 | } 32 | 33 | public void setClientId(String clientId) { 34 | this.clientId = clientId; 35 | } 36 | 37 | public String getClientSecret() { 38 | return clientSecret; 39 | } 40 | 41 | public void setClientSecret(String clientSecret) { 42 | this.clientSecret = clientSecret; 43 | } 44 | 45 | public String getStatus() { 46 | return status; 47 | } 48 | 49 | public void setStatus(String status) { 50 | this.status = status; 51 | } 52 | 53 | public String getPurpose() { 54 | return purpose; 55 | } 56 | 57 | public void setPurpose(String purpose) { 58 | this.purpose = purpose; 59 | } 60 | 61 | public UUID getTenantId() { 62 | return tenantId; 63 | } 64 | 65 | public void setTenantId(UUID tenantId) { 66 | this.tenantId = tenantId; 67 | } 68 | 69 | public UUID getUserId() { 70 | return userId; 71 | } 72 | 73 | public void setUserId(UUID userId) { 74 | this.userId = userId; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/dto/DefaultRole.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.dto; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import com.fasterxml.jackson.annotation.JsonPropertyOrder; 5 | import lombok.Data; 6 | 7 | import java.util.UUID; 8 | 9 | @JsonPropertyOrder({ 10 | "id", 11 | "name", 12 | "description"}) 13 | @Data 14 | public class DefaultRole { 15 | @JsonProperty("id") 16 | private UUID id; 17 | 18 | @JsonProperty("name") 19 | private String name; 20 | 21 | @JsonProperty("description") 22 | private String description; 23 | 24 | public DefaultRole(UUID id, String name, String description) { 25 | this.id = id; 26 | this.name = name; 27 | this.description = description; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/dto/DefaultRoles.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.dto; 2 | 3 | import java.util.UUID; 4 | 5 | /** 6 | * Created by keets on 2017/11/23. 7 | */ 8 | public class DefaultRoles { 9 | public static DefaultRole PLATFORM_ADMIN = new DefaultRole(UUID.fromString("23f59f5d-427d-401b-a676-6cca3a9d99f5"), "PLATFORM_ADMIN", "the platform admin was hold by the website administrators"); 10 | public static DefaultRole BRANCH_ADMIN = new DefaultRole(UUID.fromString("6405f6af-d892-4bf9-b13c-f7ca2ae1d71e"), "BRANCH_ADMIN", "the branch company admin"); 11 | public static DefaultRole MASTER_ADMIN = new DefaultRole(UUID.fromString("fe96c94c-e3a9-4d30-88a5-c2acbba8917d"), "MASTER_ADMIN", "the master company admin"); 12 | public static DefaultRole GENERAL_USER = new DefaultRole(UUID.fromString("7bb37b99-6d6d-403b-88c1-95d3944f5403"), "GENERAL_USER", "a normal user"); 13 | public static DefaultRole EMPLOYEE = new DefaultRole(UUID.fromString("d4a65d04-a5a3-465c-8408-405971ac3346"), "EMPLOYEE", "the employee for a company"); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/dto/RolePermissionDTO.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.dto; 2 | 3 | import com.blueskykong.auth.entity.Permission; 4 | import lombok.Data; 5 | 6 | import java.sql.Timestamp; 7 | import java.util.List; 8 | import java.util.UUID; 9 | 10 | /** 11 | * Created by keets on 2017/11/22. 12 | */ 13 | @Data 14 | public class RolePermissionDTO { 15 | 16 | private Long relationId; 17 | 18 | private UUID roleId; 19 | 20 | private String name; 21 | 22 | private Timestamp updateTime; 23 | 24 | private String description; 25 | 26 | private List permissions; 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/dto/UserRoleDTO.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.dto; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.UUID; 6 | 7 | /** 8 | * Created by keets on 2016/12/5. 9 | */ 10 | @Data 11 | public class UserRoleDTO { 12 | 13 | private UUID userId; 14 | 15 | private UUID roleId; 16 | 17 | private String name; 18 | 19 | private String description; 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/entity/BaseEntity.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.entity; 2 | 3 | import com.blueskykong.auth.utils.TimestampAdapter; 4 | import lombok.Data; 5 | 6 | import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; 7 | import java.io.Serializable; 8 | import java.sql.Timestamp; 9 | 10 | 11 | @Data 12 | public abstract class BaseEntity implements Serializable { 13 | 14 | private static final long serialVersionUID = 8388417013613884411L; 15 | 16 | @XmlJavaTypeAdapter(TimestampAdapter.class) 17 | private Timestamp createTime; 18 | 19 | @XmlJavaTypeAdapter(TimestampAdapter.class) 20 | private Timestamp updateTime; 21 | 22 | private int createBy; 23 | 24 | private int updateBy; 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/entity/ClientSecret.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.entity; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.UUID; 6 | 7 | 8 | @Data 9 | public class ClientSecret extends BaseEntity { 10 | private String clientId; 11 | private String clientSecret; 12 | private ClientSecretStatus status; 13 | private String purpose; 14 | private UUID tenantId; 15 | private UUID userId; 16 | 17 | public static class ClientSecretBuilder { 18 | 19 | private ClientSecret client = new ClientSecret(); 20 | 21 | public ClientSecretBuilder withClientId(String clientId) { 22 | client.setClientId(clientId); 23 | return this; 24 | } 25 | 26 | public ClientSecretBuilder withClientSecret(String clientSecret) { 27 | client.setClientSecret(clientSecret); 28 | return this; 29 | } 30 | 31 | public ClientSecretBuilder withStatus(ClientSecretStatus status) { 32 | client.setStatus(status); 33 | return this; 34 | } 35 | 36 | public ClientSecretBuilder withTenantId(UUID tenantId) { 37 | client.setTenantId(tenantId); 38 | return this; 39 | } 40 | 41 | public ClientSecretBuilder withPurpose(String purpose) { 42 | client.setPurpose(purpose); 43 | return this; 44 | } 45 | 46 | public ClientSecret build() { 47 | return client; 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/entity/ClientSecretStatus.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.entity; 2 | 3 | /** 4 | * Created by keets on 2016/12/5. 5 | */ 6 | public enum ClientSecretStatus { 7 | ACTIVE, INACTIVE 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/entity/Permission.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.entity; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.UUID; 6 | 7 | /** 8 | * Created by keets on 2017/11/22. 9 | */ 10 | @Data 11 | public class Permission { 12 | 13 | private UUID id; 14 | 15 | private String permission; 16 | 17 | private String description; 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/entity/Role.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.entity; 2 | 3 | import lombok.Data; 4 | 5 | import java.sql.Timestamp; 6 | import java.util.UUID; 7 | 8 | 9 | @Data 10 | public class Role { 11 | 12 | private UUID id; 13 | 14 | private String name; 15 | 16 | private Timestamp updateTime; 17 | 18 | private String description; 19 | 20 | public static class RoleBuilder { 21 | private Role role = new Role(); 22 | 23 | public RoleBuilder withId(UUID id) { 24 | role.setId(id); 25 | return this; 26 | } 27 | 28 | public RoleBuilder withName(String name) { 29 | role.setName(name); 30 | return this; 31 | } 32 | 33 | public RoleBuilder withDescription(String description) { 34 | role.setDescription(description); 35 | return this; 36 | } 37 | 38 | public RoleBuilder withUpdateTime(Timestamp time) { 39 | role.setUpdateTime(time); 40 | return this; 41 | } 42 | 43 | public Role build() { 44 | return role; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/entity/RolePermission.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.entity; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.UUID; 6 | 7 | 8 | @Data 9 | public class RolePermission { 10 | 11 | private Long id; 12 | 13 | private UUID roleId; 14 | 15 | private UUID permissionId; 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/entity/UserAccess.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.entity; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.UUID; 6 | 7 | @Data 8 | public class UserAccess { 9 | private Long id; 10 | 11 | private UUID userId; 12 | 13 | private Integer accessLevel; 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/entity/UserRole.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.entity; 2 | 3 | import lombok.Data; 4 | 5 | import java.util.UUID; 6 | 7 | @Data 8 | public class UserRole { 9 | private Long id; 10 | 11 | private UUID userId; 12 | 13 | private UUID roleId; 14 | 15 | private Boolean isDefault = true; 16 | 17 | public static class UserRoleBuilder { 18 | 19 | private UserRole userRole = new UserRole(); 20 | 21 | public UserRoleBuilder withUserId(UUID userId) { 22 | userRole.setUserId(userId); 23 | return this; 24 | } 25 | 26 | public UserRoleBuilder withRoleId(UUID roleId) { 27 | userRole.setRoleId(roleId); 28 | return this; 29 | } 30 | 31 | public UserRole build() { 32 | return userRole; 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/exception/AbstractException.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.exception; 2 | 3 | 4 | import org.springframework.http.HttpStatus; 5 | 6 | import java.io.PrintWriter; 7 | import java.io.StringWriter; 8 | 9 | public abstract class AbstractException extends RuntimeException { 10 | private static final long serialVersionUID = 1L; 11 | 12 | private final HttpStatus status; 13 | 14 | private final int code; 15 | 16 | private final String message; 17 | 18 | private final String detailMessage; 19 | 20 | public AbstractException(HttpStatus status, ErrorCode errorCode) { 21 | this.status = status; 22 | this.code = errorCode.getCode(); 23 | this.message = errorCode.getMessage(); 24 | this.detailMessage = errorCode.getDetailMessage(); 25 | } 26 | 27 | public AbstractException(HttpStatus status) { 28 | this.status = status; 29 | code = 0; 30 | message = null; 31 | detailMessage = null; 32 | } 33 | 34 | public AbstractException(HttpStatus status, ErrorCode errorCode, Throwable cause) { 35 | super(cause); 36 | this.status = status; 37 | this.code = errorCode.getCode(); 38 | this.message = errorCode.getMessage(); 39 | detailMessage = (cause.getMessage() != null ? cause.getMessage() : "") + toStackTrace(cause); 40 | } 41 | 42 | private String toStackTrace(Throwable e) { 43 | StringWriter errorStackTrace = new StringWriter(); 44 | e.printStackTrace(new PrintWriter(errorStackTrace)); 45 | return errorStackTrace.toString(); 46 | 47 | } 48 | 49 | public HttpStatus getStatus() { 50 | return status; 51 | } 52 | 53 | public ErrorCode getCode() { 54 | return new ErrorCode(code,message,detailMessage); 55 | } 56 | 57 | @Override 58 | public String getMessage() { 59 | return message; 60 | } 61 | 62 | public String getDetailMessage() { 63 | return detailMessage; 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/exception/CustomWebResponseExceptionTranslator.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.exception; 2 | 3 | import com.netflix.hystrix.exception.HystrixRuntimeException; 4 | import org.apache.commons.lang.StringUtils; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | import org.springframework.http.HttpHeaders; 8 | import org.springframework.http.HttpStatus; 9 | import org.springframework.http.MediaType; 10 | import org.springframework.http.ResponseEntity; 11 | import org.springframework.security.oauth2.common.exceptions.OAuth2Exception; 12 | import org.springframework.security.oauth2.provider.error.DefaultWebResponseExceptionTranslator; 13 | 14 | public class CustomWebResponseExceptionTranslator extends DefaultWebResponseExceptionTranslator { 15 | 16 | private static final Logger LOGGER = LoggerFactory.getLogger(CustomWebResponseExceptionTranslator.class); 17 | 18 | @Override 19 | public ResponseEntity translate(Exception e) throws Exception { 20 | OAuth2Exception oAuth2Exception; 21 | HttpHeaders headers = new HttpHeaders(); 22 | int httpStatus; 23 | 24 | if (e instanceof HystrixRuntimeException) { 25 | Throwable actual = ((HystrixRuntimeException) e).getFallbackException().getCause().getCause(); 26 | 27 | oAuth2Exception = new OAuth2Exception(actual.getMessage()); 28 | 29 | String code; 30 | String message; 31 | 32 | if (actual instanceof AbstractException) { 33 | httpStatus = ((AbstractException) actual).getStatus().value(); 34 | code = ((AbstractException) actual).getCode().getCode()+""; 35 | message = ((AbstractException) actual).getCode().getMessage(); 36 | LOGGER.error("AbstractException", actual); 37 | } else { 38 | httpStatus = HttpStatus.INTERNAL_SERVER_ERROR.value(); 39 | code = GenericErrorCodes.GENERIC_API_ERROR_CODE.getCode() + ""; 40 | message = GenericErrorCodes.GENERIC_API_ERROR_CODE.getMessage(); 41 | LOGGER.error("HystrixRuntimeException", actual); 42 | } 43 | 44 | oAuth2Exception.addAdditionalInformation("code", code); 45 | oAuth2Exception.addAdditionalInformation("message", message); 46 | } else { 47 | ResponseEntity responseEntity = super.translate(e); 48 | oAuth2Exception = responseEntity.getBody(); 49 | httpStatus = HttpStatus.UNAUTHORIZED.value(); 50 | 51 | String errorCode = oAuth2Exception.getMessage(); 52 | 53 | oAuth2Exception.addAdditionalInformation("code", StringUtils.isNotEmpty(errorCode) ? errorCode : GenericErrorCodes.GENERIC_API_ERROR_CODE.getCode() + ""); 54 | oAuth2Exception.addAdditionalInformation("message", "账号认证失败"); 55 | LOGGER.error("OAuth2Exception", oAuth2Exception); 56 | } 57 | 58 | headers.setContentType(MediaType.APPLICATION_JSON); 59 | return new ResponseEntity<>(oAuth2Exception, headers, HttpStatus.valueOf(httpStatus)); 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/exception/ErrorCode.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.exception; 2 | 3 | 4 | public class ErrorCode { 5 | 6 | private final int code; 7 | private final String message; 8 | private final String detailMessage; 9 | 10 | public ErrorCode(int code, String message, String detailMessage) { 11 | this.code = code; 12 | this.message = message; 13 | this.detailMessage = detailMessage; 14 | } 15 | 16 | public ErrorCode(String message, String detailMessage) { 17 | this.code = 0; 18 | this.message = message; 19 | this.detailMessage = detailMessage; 20 | } 21 | 22 | public int getCode() { 23 | return code; 24 | } 25 | 26 | public String getMessage() { 27 | return message; 28 | } 29 | 30 | public String getDetailMessage() { 31 | return detailMessage; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/exception/ErrorCodes.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.exception; 2 | 3 | public class ErrorCodes { 4 | 5 | public static final String CLIENT_ID_IS_NULL_STR = "CLIENT_ID_IS_NULL"; 6 | public static final String CLIENT_SECRET_IS_NULL_STR = "CLIENT_SECRET_IS_NULL"; 7 | 8 | public static final String ORGANIZAITON_ID_IS_NULL_STR = "ORGANIZAITON_ID_IS_NULL"; 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/exception/GenericErrorCodes.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.exception; 2 | 3 | public class GenericErrorCodes { 4 | public static ErrorCode GENERIC_API_ERROR_CODE = new ErrorCode(0001, "GENERIC_API_ERROR_CODE", "generic API error message"); 5 | public static ErrorCode GENERIC_UNAUTHORIZED_ERROR_CODE = new ErrorCode(0002, "GENERIC_UNAUTHORIZED_ERROR_CODE", "generic unauthorized error message"); 6 | public static ErrorCode DATA_ACCESS_ERROR_CODE = new ErrorCode(0003, "DATA_ACCESS_ERROR", "database access error"); 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/properties/RedisProperties.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.properties; 2 | 3 | public class RedisProperties { 4 | 5 | private String host; 6 | 7 | private Integer port; 8 | 9 | public String getHost() { 10 | return host; 11 | } 12 | 13 | public void setHost(String host) { 14 | this.host = host; 15 | } 16 | 17 | public Integer getPort() { 18 | return port; 19 | } 20 | 21 | public void setPort(Integer port) { 22 | this.port = port; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/rest/ClientSecretResource.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.rest; 2 | 3 | import com.blueskykong.auth.dto.ApiClientDTO; 4 | import com.blueskykong.auth.entity.ClientSecretStatus; 5 | import com.blueskykong.auth.service.ClientSecretService; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | 8 | import javax.ws.rs.*; 9 | import javax.ws.rs.core.MediaType; 10 | import javax.ws.rs.core.Response; 11 | import java.util.List; 12 | import java.util.UUID; 13 | 14 | /** 15 | * @author keets 16 | * @date 2017/9/18 17 | */ 18 | @Path("/") 19 | public class ClientSecretResource { 20 | 21 | @Autowired 22 | private ClientSecretService clientSecretService; 23 | 24 | @POST 25 | @Produces(MediaType.APPLICATION_JSON) 26 | @Consumes(MediaType.APPLICATION_JSON) 27 | @Path("/clients") 28 | public Response createClient(ApiClientDTO apiClientDTO) { 29 | clientSecretService.createClientSecret(apiClientDTO); 30 | return Response.status(Response.Status.CREATED).build(); 31 | } 32 | 33 | @GET 34 | @Produces(MediaType.APPLICATION_JSON) 35 | @Consumes(MediaType.APPLICATION_JSON) 36 | @Path("/clients/{clientId}") 37 | public Response getClient(@PathParam("clientId") String clientId) { 38 | ApiClientDTO apiClientDTO = clientSecretService.getClientSecretByClientId(clientId); 39 | return Response.ok(apiClientDTO).build(); 40 | } 41 | 42 | 43 | @PUT 44 | @Produces(MediaType.APPLICATION_JSON) 45 | @Consumes(MediaType.APPLICATION_JSON) 46 | @Path("/clients/{clientId}") 47 | public Response updateClient(@PathParam("clientId") String clientId, ApiClientDTO apiClientDTO) { 48 | clientSecretService.updateClientSecret(apiClientDTO); 49 | return Response.ok().build(); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/rest/SecurityResource.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.rest; 2 | 3 | import com.blueskykong.auth.dao.PermissionDAO; 4 | import com.blueskykong.auth.dao.RoleDAO; 5 | import com.blueskykong.auth.dao.RolePermissionDAO; 6 | import com.blueskykong.auth.dao.UserRoleDAO; 7 | import com.blueskykong.auth.dto.UserRoleDTO; 8 | import com.blueskykong.auth.entity.Permission; 9 | import com.blueskykong.auth.entity.RolePermission; 10 | import com.blueskykong.auth.entity.UserRole; 11 | import com.blueskykong.auth.service.SecurityService; 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | import org.springframework.beans.factory.annotation.Autowired; 15 | 16 | import javax.ws.rs.Consumes; 17 | import javax.ws.rs.GET; 18 | import javax.ws.rs.POST; 19 | import javax.ws.rs.Path; 20 | import javax.ws.rs.PathParam; 21 | import javax.ws.rs.Produces; 22 | import javax.ws.rs.core.MediaType; 23 | import javax.ws.rs.core.Response; 24 | import java.util.UUID; 25 | 26 | /** 27 | * @author keets 28 | * @date 2017/10/15 29 | */ 30 | @Path("/") 31 | public class SecurityResource { 32 | private static final Logger LOGGER = LoggerFactory.getLogger(SecurityResource.class); 33 | 34 | @Autowired 35 | private SecurityService securityService; 36 | 37 | @Autowired 38 | private UserRoleDAO userRoleDAO; 39 | 40 | @Autowired 41 | private PermissionDAO permissionDAO; 42 | 43 | @Autowired 44 | private RoleDAO roleDAO; 45 | 46 | @Autowired 47 | private RolePermissionDAO rolePermissionDAO; 48 | 49 | @POST 50 | @Path("permission") 51 | @Consumes(MediaType.APPLICATION_JSON) 52 | @Produces(MediaType.APPLICATION_JSON) 53 | public Response createPermission(Permission permission) { 54 | permission.setId(UUID.randomUUID()); 55 | permissionDAO.insert(permission); 56 | return Response.ok(permission.getId()).build(); 57 | } 58 | 59 | @GET 60 | @Path("permissions/{id}") 61 | @Consumes(MediaType.APPLICATION_JSON) 62 | @Produces(MediaType.APPLICATION_JSON) 63 | public Response listPermission(@PathParam("id") String id) { 64 | UUID pId = UUID.fromString(id); 65 | Permission permission = permissionDAO.selectById(pId); 66 | return Response.ok(permission).build(); 67 | } 68 | 69 | @POST 70 | @Path("/role-permission") 71 | @Consumes(MediaType.APPLICATION_JSON) 72 | public Response createRolePermission(RolePermission rolePermission) { 73 | rolePermissionDAO.insert(rolePermission); 74 | return Response.ok().build(); 75 | } 76 | 77 | @GET 78 | @Path("role") 79 | @Produces(MediaType.APPLICATION_JSON) 80 | public Response listRoles() { 81 | return Response.ok(roleDAO.selectAll()).build(); 82 | } 83 | 84 | @GET 85 | @Path("permissions") 86 | @Produces(MediaType.APPLICATION_JSON) 87 | public Response listPermissions() { 88 | return Response.ok(permissionDAO.selectAll()).build(); 89 | } 90 | 91 | @POST 92 | @Path("user-role") 93 | @Produces(MediaType.APPLICATION_JSON) 94 | public Response createUserRole(UserRole userRole) { 95 | userRole.setUserId(UUID.randomUUID()); 96 | userRoleDAO.insertUtRole(userRole); 97 | return Response.ok().build(); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/rest/UserRoleResource.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.rest; 2 | 3 | import com.blueskykong.auth.dto.RolePermissionDTO; 4 | import com.blueskykong.auth.entity.Permission; 5 | import com.blueskykong.auth.service.SecurityService; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | 8 | import javax.ws.rs.GET; 9 | import javax.ws.rs.Path; 10 | import javax.ws.rs.Produces; 11 | import javax.ws.rs.QueryParam; 12 | import javax.ws.rs.core.MediaType; 13 | import javax.ws.rs.core.Response; 14 | import java.util.List; 15 | import java.util.UUID; 16 | 17 | /** 18 | * @author keets 19 | * @date 2017/11/22 20 | */ 21 | @Path("/") 22 | public class UserRoleResource { 23 | 24 | @Autowired 25 | SecurityService securityService; 26 | 27 | @GET 28 | @Produces(MediaType.APPLICATION_JSON) 29 | @Path("/userRolePermissions") 30 | public Response getUserRolePermissions(@QueryParam("userId") String userId) { 31 | List rolePermissions = securityService.getRolePermissionsByUserId(UUID.fromString(userId)); 32 | return Response.ok(rolePermissions).build(); 33 | } 34 | 35 | @GET 36 | @Produces(MediaType.APPLICATION_JSON) 37 | @Path("/userPermissions") 38 | public Response getPermissionList(@QueryParam("userId") String userId) { 39 | List permissionList = securityService.getPermissionListByUserId(userId); 40 | return Response.ok(permissionList).build(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/security/CodeAuthenticationProvider.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.security; 2 | 3 | import com.auth0.jwt.internal.org.apache.commons.lang3.StringUtils; 4 | import org.springframework.security.authentication.AuthenticationProvider; 5 | import org.springframework.security.authentication.BadCredentialsException; 6 | import org.springframework.security.core.Authentication; 7 | import org.springframework.security.core.AuthenticationException; 8 | import org.springframework.stereotype.Component; 9 | 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | import java.util.UUID; 13 | 14 | /** 15 | * 这里模拟的是授权码登录时候的身份认证 16 | * 授权码登录验证的界面可以根据需要自定义 17 | * Created by xuan on 2018/1/3. 18 | */ 19 | @Component 20 | public class CodeAuthenticationProvider implements AuthenticationProvider { 21 | 22 | 23 | @Override 24 | public Authentication authenticate(Authentication authentication) throws AuthenticationException { 25 | String username = authentication.getName(); 26 | String password; 27 | 28 | Map map; 29 | 30 | password = (String) authentication.getCredentials(); 31 | //如果你是调用user服务,这边不用注掉 32 | //map = userClient.checkUsernameAndPassword(getUserServicePostObject(username, password, type)); 33 | map = checkUsernameAndPassword(getUserServicePostObject(username, password)); 34 | 35 | 36 | String userId = (String) map.get("userId"); 37 | if (StringUtils.isBlank(userId)) { 38 | String errorCode = (String) map.get("code"); 39 | throw new BadCredentialsException(errorCode); 40 | } 41 | CustomUserDetails customUserDetails = buildCustomUserDetails(username, password, userId); 42 | return new CustomAuthenticationToken(customUserDetails); 43 | } 44 | 45 | private CustomUserDetails buildCustomUserDetails(String username, String password, String userId) { 46 | CustomUserDetails customUserDetails = new CustomUserDetails.CustomUserDetailsBuilder() 47 | .withUserId(userId) 48 | .withPassword(password) 49 | .withUsername(username) 50 | .withClientId("frontend") 51 | .build(); 52 | return customUserDetails; 53 | } 54 | 55 | private Map getUserServicePostObject(String username, String password) { 56 | Map requestParam = new HashMap(); 57 | requestParam.put("userName", username); 58 | requestParam.put("password", password); 59 | return requestParam; 60 | } 61 | 62 | //模拟调用user服务的方法 63 | private Map checkUsernameAndPassword(Map map) { 64 | 65 | //checkUsernameAndPassword 66 | Map ret = new HashMap(); 67 | ret.put("userId", UUID.randomUUID().toString()); 68 | 69 | return ret; 70 | } 71 | 72 | @Override 73 | public boolean supports(Class aClass) { 74 | return true; 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/security/CustomAuthenticationProvider.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.security; 2 | 3 | import com.auth0.jwt.internal.org.apache.commons.lang3.StringUtils; 4 | import org.springframework.security.authentication.AuthenticationProvider; 5 | import org.springframework.security.authentication.BadCredentialsException; 6 | import org.springframework.security.core.Authentication; 7 | import org.springframework.security.core.AuthenticationException; 8 | import org.springframework.stereotype.Component; 9 | import org.springframework.util.Assert; 10 | 11 | import java.util.HashMap; 12 | import java.util.Map; 13 | import java.util.UUID; 14 | 15 | /** 16 | * @author keets 17 | * @date 2017/8/5 18 | */ 19 | @Component 20 | public class CustomAuthenticationProvider implements AuthenticationProvider { 21 | 22 | 23 | @Override 24 | public Authentication authenticate(Authentication authentication) throws AuthenticationException { 25 | String username = authentication.getName(); 26 | String password; 27 | Map data; 28 | if(authentication.getDetails() instanceof Map) { 29 | data = (Map) authentication.getDetails(); 30 | }else{ 31 | return null; 32 | } 33 | String clientId = (String) data.get("client"); 34 | Assert.hasText(clientId, "clientId must have value"); 35 | String type = (String) data.get("type"); 36 | Map map; 37 | 38 | password = (String) authentication.getCredentials(); 39 | //如果你是调用user服务,这边不用注掉 40 | //map = userClient.checkUsernameAndPassword(getUserServicePostObject(username, password, type)); 41 | map = checkUsernameAndPassword(getUserServicePostObject(username, password, type)); 42 | 43 | 44 | String userId = (String) map.get("userId"); 45 | if (StringUtils.isBlank(userId)) { 46 | String errorCode = (String) map.get("code"); 47 | throw new BadCredentialsException(errorCode); 48 | } 49 | CustomUserDetails customUserDetails = buildCustomUserDetails(username, password, userId, clientId); 50 | return new CustomAuthenticationToken(customUserDetails); 51 | } 52 | 53 | private CustomUserDetails buildCustomUserDetails(String username, String password, String userId, String clientId) { 54 | CustomUserDetails customUserDetails = new CustomUserDetails.CustomUserDetailsBuilder() 55 | .withUserId(userId) 56 | .withPassword(password) 57 | .withUsername(username) 58 | .withClientId(clientId) 59 | .build(); 60 | return customUserDetails; 61 | } 62 | 63 | private Map getUserServicePostObject(String username, String password, String type) { 64 | Map requestParam = new HashMap(); 65 | requestParam.put("userName", username); 66 | requestParam.put("password", password); 67 | if (type != null && StringUtils.isNotBlank(type)) { 68 | requestParam.put("type", type); 69 | } 70 | return requestParam; 71 | } 72 | 73 | //模拟调用user服务的方法 74 | private Map checkUsernameAndPassword(Map map) { 75 | 76 | //checkUsernameAndPassword 77 | Map ret = new HashMap(); 78 | ret.put("userId", UUID.randomUUID().toString()); 79 | 80 | return ret; 81 | } 82 | 83 | @Override 84 | public boolean supports(Class aClass) { 85 | return true; 86 | } 87 | 88 | } -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/security/CustomAuthenticationToken.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.security; 2 | 3 | import org.springframework.security.authentication.AbstractAuthenticationToken; 4 | 5 | /** 6 | * Created by keets on 2017/8/5. 7 | */ 8 | public class CustomAuthenticationToken extends AbstractAuthenticationToken { 9 | 10 | private CustomUserDetails userDetails; 11 | 12 | public CustomAuthenticationToken(CustomUserDetails userDetails) { 13 | super(null); 14 | this.userDetails = userDetails; 15 | super.setAuthenticated(true); 16 | } 17 | 18 | public Object getPrincipal() { 19 | return this.userDetails; 20 | } 21 | 22 | public Object getCredentials() { 23 | return this.userDetails.getPassword(); 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/security/CustomAuthorizationTokenServices.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.security; 2 | 3 | import org.springframework.security.authentication.AuthenticationManager; 4 | import org.springframework.security.core.Authentication; 5 | import org.springframework.security.core.AuthenticationException; 6 | import org.springframework.security.oauth2.common.*; 7 | import org.springframework.security.oauth2.common.exceptions.InvalidGrantException; 8 | import org.springframework.security.oauth2.common.exceptions.InvalidScopeException; 9 | import org.springframework.security.oauth2.common.exceptions.InvalidTokenException; 10 | import org.springframework.security.oauth2.provider.*; 11 | import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices; 12 | import org.springframework.security.oauth2.provider.token.ConsumerTokenServices; 13 | import org.springframework.security.oauth2.provider.token.TokenEnhancer; 14 | import org.springframework.security.oauth2.provider.token.TokenStore; 15 | import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken; 16 | import org.springframework.transaction.annotation.Transactional; 17 | import org.springframework.util.Assert; 18 | 19 | import java.util.Date; 20 | import java.util.Set; 21 | import java.util.UUID; 22 | 23 | /** 24 | * Created by keets on 2017/8/5. 25 | */ 26 | public class CustomAuthorizationTokenServices implements AuthorizationServerTokenServices, ConsumerTokenServices { 27 | 28 | private int refreshTokenValiditySeconds = 60 * 60 * 24 * 30; // default 30 days. 29 | 30 | private int accessTokenValiditySeconds = 60 * 60 * 12; // default 12 hours. 31 | 32 | private boolean supportRefreshToken = false; 33 | 34 | private boolean reuseRefreshToken = true; 35 | 36 | private TokenStore tokenStore; 37 | 38 | private ClientDetailsService clientDetailsService; 39 | 40 | private TokenEnhancer accessTokenEnhancer; 41 | 42 | private AuthenticationManager authenticationManager; 43 | 44 | /** 45 | * Initialize these token services. If no random generator is set, one will be created. 46 | */ 47 | public void afterPropertiesSet() throws Exception { 48 | Assert.notNull(tokenStore, "tokenStore must be set"); 49 | } 50 | 51 | @Override 52 | @Transactional 53 | public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) throws AuthenticationException { 54 | 55 | OAuth2AccessToken existingAccessToken = tokenStore.getAccessToken(authentication); 56 | OAuth2RefreshToken refreshToken; 57 | 58 | if (existingAccessToken != null) { 59 | if (existingAccessToken.getRefreshToken() != null) { 60 | refreshToken = existingAccessToken.getRefreshToken(); 61 | tokenStore.removeRefreshToken(refreshToken); 62 | } 63 | tokenStore.removeAccessToken(existingAccessToken); 64 | } 65 | //recreate a refreshToken 66 | refreshToken = createRefreshToken(authentication); 67 | 68 | OAuth2AccessToken accessToken = createAccessToken(authentication, refreshToken); 69 | if (accessToken != null) { 70 | tokenStore.storeAccessToken(accessToken, authentication); 71 | } 72 | refreshToken = accessToken.getRefreshToken(); 73 | if (refreshToken != null) { 74 | tokenStore.storeRefreshToken(refreshToken, authentication); 75 | } 76 | return accessToken; 77 | } 78 | 79 | @Override 80 | @Transactional(noRollbackFor = {InvalidTokenException.class, InvalidGrantException.class}) 81 | public OAuth2AccessToken refreshAccessToken(String refreshTokenValue, TokenRequest tokenRequest) 82 | throws AuthenticationException { 83 | 84 | if (!supportRefreshToken) { 85 | throw new InvalidGrantException("Invalid refresh token: " + refreshTokenValue); 86 | } 87 | 88 | OAuth2RefreshToken refreshToken = tokenStore.readRefreshToken(refreshTokenValue); 89 | if (refreshToken == null) { 90 | throw new InvalidGrantException("Invalid refresh token: " + refreshTokenValue); 91 | } 92 | 93 | OAuth2Authentication authentication = tokenStore.readAuthenticationForRefreshToken(refreshToken); 94 | if (this.authenticationManager != null && !authentication.isClientOnly()) { 95 | Authentication user = new PreAuthenticatedAuthenticationToken(authentication.getUserAuthentication(), "", authentication.getAuthorities()); 96 | 97 | // Overrides this section, because he followed std's oAuth2 refresh token mechanism to skip the scope of use check.changes 98 | //user = authenticationManager.authenticate(user); 99 | Object details = authentication.getDetails(); 100 | authentication = new OAuth2Authentication(authentication.getOAuth2Request(), user); 101 | authentication.setDetails(details); 102 | } 103 | String clientId = authentication.getOAuth2Request().getClientId(); 104 | if (clientId == null || !clientId.equals(tokenRequest.getClientId())) { 105 | throw new InvalidGrantException("Wrong client for this refresh token: " + refreshTokenValue); 106 | } 107 | 108 | // clear out any access tokens already associated with the refresh 109 | // token. 110 | tokenStore.removeAccessTokenUsingRefreshToken(refreshToken); 111 | 112 | if (isExpired(refreshToken)) { 113 | tokenStore.removeRefreshToken(refreshToken); 114 | throw new InvalidTokenException("Invalid refresh token (expired): " + refreshToken); 115 | } 116 | 117 | authentication = createRefreshedAuthentication(authentication, tokenRequest); 118 | 119 | if (!reuseRefreshToken) { 120 | tokenStore.removeRefreshToken(refreshToken); 121 | refreshToken = createRefreshToken(authentication); 122 | } 123 | 124 | OAuth2AccessToken accessToken = createAccessToken(authentication, refreshToken); 125 | tokenStore.storeAccessToken(accessToken, authentication); 126 | if (!reuseRefreshToken) { 127 | tokenStore.storeRefreshToken(accessToken.getRefreshToken(), authentication); 128 | } 129 | return accessToken; 130 | } 131 | 132 | @Override 133 | public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { 134 | return tokenStore.getAccessToken(authentication); 135 | } 136 | 137 | /** 138 | * Create a refreshed authentication. 139 | * 140 | * @param authentication The authentication. 141 | * @param request The scope for the refreshed token. 142 | * @return The refreshed authentication. 143 | * @throws InvalidScopeException If the scope requested is invalid or wider than the original scope. 144 | */ 145 | private OAuth2Authentication createRefreshedAuthentication(OAuth2Authentication authentication, TokenRequest request) { 146 | OAuth2Authentication narrowed = authentication; 147 | Set scope = request.getScope(); 148 | OAuth2Request clientAuth = authentication.getOAuth2Request().refresh(request); 149 | if (scope != null && !scope.isEmpty()) { 150 | Set originalScope = clientAuth.getScope(); 151 | if (originalScope == null || !originalScope.containsAll(scope)) { 152 | throw new InvalidScopeException("Unable to narrow the scope of the client authentication to " + scope 153 | + ".", originalScope); 154 | } else { 155 | clientAuth = clientAuth.narrowScope(scope); 156 | } 157 | } 158 | narrowed = new OAuth2Authentication(clientAuth, authentication.getUserAuthentication()); 159 | return narrowed; 160 | } 161 | 162 | protected boolean isExpired(OAuth2RefreshToken refreshToken) { 163 | if (refreshToken instanceof ExpiringOAuth2RefreshToken) { 164 | ExpiringOAuth2RefreshToken expiringToken = (ExpiringOAuth2RefreshToken) refreshToken; 165 | return expiringToken.getExpiration() == null 166 | || System.currentTimeMillis() > expiringToken.getExpiration().getTime(); 167 | } 168 | return false; 169 | } 170 | 171 | public OAuth2AccessToken readAccessToken(String accessToken) { 172 | return tokenStore.readAccessToken(accessToken); 173 | } 174 | 175 | public OAuth2Authentication loadAuthentication(String accessTokenValue) throws AuthenticationException, 176 | InvalidTokenException { 177 | OAuth2AccessToken accessToken = tokenStore.readAccessToken(accessTokenValue); 178 | if (accessToken == null) { 179 | throw new InvalidTokenException("Invalid access token: " + accessTokenValue); 180 | } else if (accessToken.isExpired()) { 181 | tokenStore.removeAccessToken(accessToken); 182 | throw new InvalidTokenException("Access token expired: " + accessTokenValue); 183 | } 184 | 185 | OAuth2Authentication result = tokenStore.readAuthentication(accessToken); 186 | if (result == null) { 187 | // in case of race condition 188 | throw new InvalidTokenException("Invalid access token: " + accessTokenValue); 189 | } 190 | if (clientDetailsService != null) { 191 | String clientId = result.getOAuth2Request().getClientId(); 192 | try { 193 | clientDetailsService.loadClientByClientId(clientId); 194 | } catch (ClientRegistrationException e) { 195 | throw new InvalidTokenException("Client not valid: " + clientId, e); 196 | } 197 | } 198 | return result; 199 | } 200 | 201 | public String getClientId(String tokenValue) { 202 | OAuth2Authentication authentication = tokenStore.readAuthentication(tokenValue); 203 | if (authentication == null) { 204 | throw new InvalidTokenException("Invalid access token: " + tokenValue); 205 | } 206 | OAuth2Request clientAuth = authentication.getOAuth2Request(); 207 | if (clientAuth == null) { 208 | throw new InvalidTokenException("Invalid access token (no client id): " + tokenValue); 209 | } 210 | return clientAuth.getClientId(); 211 | } 212 | 213 | @Override 214 | public boolean revokeToken(String tokenValue) { 215 | OAuth2AccessToken accessToken = tokenStore.readAccessToken(tokenValue); 216 | if (accessToken == null) { 217 | return false; 218 | } 219 | if (accessToken.getRefreshToken() != null) { 220 | tokenStore.removeRefreshToken(accessToken.getRefreshToken()); 221 | } 222 | tokenStore.removeAccessToken(accessToken); 223 | return true; 224 | } 225 | 226 | private OAuth2RefreshToken createRefreshToken(OAuth2Authentication authentication) { 227 | if (!isSupportRefreshToken(authentication.getOAuth2Request())) { 228 | return null; 229 | } 230 | int validitySeconds = getRefreshTokenValiditySeconds(authentication.getOAuth2Request()); 231 | String value = UUID.randomUUID().toString(); 232 | if (validitySeconds > 0) { 233 | return new DefaultExpiringOAuth2RefreshToken(value, new Date(System.currentTimeMillis() 234 | + (validitySeconds * 1000L))); 235 | } 236 | return new DefaultOAuth2RefreshToken(value); 237 | } 238 | 239 | private OAuth2AccessToken createAccessToken(OAuth2Authentication authentication, OAuth2RefreshToken refreshToken) { 240 | DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(UUID.randomUUID().toString()); 241 | int validitySeconds = getAccessTokenValiditySeconds(authentication.getOAuth2Request()); 242 | if (validitySeconds > 0) { 243 | token.setExpiration(new Date(System.currentTimeMillis() + (validitySeconds * 1000L))); 244 | } 245 | token.setRefreshToken(refreshToken); 246 | token.setScope(authentication.getOAuth2Request().getScope()); 247 | 248 | return accessTokenEnhancer != null ? accessTokenEnhancer.enhance(token, authentication) : token; 249 | } 250 | 251 | /** 252 | * The access token validity period in seconds 253 | * 254 | * @param clientAuth the current authorization request 255 | * @return the access token validity period in seconds 256 | */ 257 | protected int getAccessTokenValiditySeconds(OAuth2Request clientAuth) { 258 | if (clientDetailsService != null) { 259 | ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId()); 260 | Integer validity = client.getAccessTokenValiditySeconds(); 261 | if (validity != null) { 262 | return validity; 263 | } 264 | } 265 | return accessTokenValiditySeconds; 266 | } 267 | 268 | /** 269 | * The refresh token validity period in seconds 270 | * 271 | * @param clientAuth the current authorization request 272 | * @return the refresh token validity period in seconds 273 | */ 274 | protected int getRefreshTokenValiditySeconds(OAuth2Request clientAuth) { 275 | if (clientDetailsService != null) { 276 | ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId()); 277 | Integer validity = client.getRefreshTokenValiditySeconds(); 278 | if (validity != null) { 279 | return validity; 280 | } 281 | } 282 | return refreshTokenValiditySeconds; 283 | } 284 | 285 | /** 286 | * Is a refresh token supported for this client (or the global setting if 287 | * {@link #setClientDetailsService(ClientDetailsService) clientDetailsService} is not set. 288 | * 289 | * @param clientAuth the current authorization request 290 | * @return boolean to indicate if refresh token is supported 291 | */ 292 | protected boolean isSupportRefreshToken(OAuth2Request clientAuth) { 293 | if (clientDetailsService != null) { 294 | ClientDetails client = clientDetailsService.loadClientByClientId(clientAuth.getClientId()); 295 | return client.getAuthorizedGrantTypes().contains("refresh_token"); 296 | } 297 | return this.supportRefreshToken; 298 | } 299 | 300 | /** 301 | * An access token enhancer that will be applied to a new token before it is saved in the token store. 302 | * 303 | * @param accessTokenEnhancer the access token enhancer to set 304 | */ 305 | public void setTokenEnhancer(TokenEnhancer accessTokenEnhancer) { 306 | this.accessTokenEnhancer = accessTokenEnhancer; 307 | } 308 | 309 | /** 310 | * The validity (in seconds) of the refresh token. If less than or equal to zero then the tokens will be 311 | * non-expiring. 312 | * 313 | * @param refreshTokenValiditySeconds The validity (in seconds) of the refresh token. 314 | */ 315 | public void setRefreshTokenValiditySeconds(int refreshTokenValiditySeconds) { 316 | this.refreshTokenValiditySeconds = refreshTokenValiditySeconds; 317 | } 318 | 319 | /** 320 | * The default validity (in seconds) of the access token. Zero or negative for non-expiring tokens. If a client 321 | * details service is set the validity period will be read from he client, defaulting to this value if not defined 322 | * by the client. 323 | * 324 | * @param accessTokenValiditySeconds The validity (in seconds) of the access token. 325 | */ 326 | public void setAccessTokenValiditySeconds(int accessTokenValiditySeconds) { 327 | this.accessTokenValiditySeconds = accessTokenValiditySeconds; 328 | } 329 | 330 | /** 331 | * Whether to support the refresh token. 332 | * 333 | * @param supportRefreshToken Whether to support the refresh token. 334 | */ 335 | public void setSupportRefreshToken(boolean supportRefreshToken) { 336 | this.supportRefreshToken = supportRefreshToken; 337 | } 338 | 339 | /** 340 | * Whether to reuse refresh tokens (until expired). 341 | * 342 | * @param reuseRefreshToken Whether to reuse refresh tokens (until expired). 343 | */ 344 | public void setReuseRefreshToken(boolean reuseRefreshToken) { 345 | this.reuseRefreshToken = reuseRefreshToken; 346 | } 347 | 348 | /** 349 | * The persistence strategy for token storage. 350 | * 351 | * @param tokenStore the store for access and refresh tokens. 352 | */ 353 | public void setTokenStore(TokenStore tokenStore) { 354 | this.tokenStore = tokenStore; 355 | } 356 | 357 | /** 358 | * An authentication manager that will be used (if provided) to check the user authentication when a token is 359 | * refreshed. 360 | * 361 | * @param authenticationManager the authenticationManager to set 362 | */ 363 | public void setAuthenticationManager(AuthenticationManager authenticationManager) { 364 | this.authenticationManager = authenticationManager; 365 | } 366 | 367 | /** 368 | * The client details service to use for looking up clients (if necessary). Optional if the access token expiry is 369 | * set globally via {@link #setAccessTokenValiditySeconds(int)}. 370 | * 371 | * @param clientDetailsService the client details service 372 | */ 373 | public void setClientDetailsService(ClientDetailsService clientDetailsService) { 374 | this.clientDetailsService = clientDetailsService; 375 | } 376 | 377 | } 378 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/security/CustomCheckPermission.java: -------------------------------------------------------------------------------- 1 | /* 2 | package com.blueskykong.auth.security; 3 | 4 | import org.springframework.security.oauth2.provider.CheckPermissions; 5 | import org.springframework.security.oauth2.provider.entity.CheckTokenEntity; 6 | import org.springframework.stereotype.Component; 7 | 8 | 9 | */ 10 | /** 11 | * 12 | * @author keets 13 | * @date 2017/9/25 14 | *//* 15 | 16 | @Component 17 | public class CustomCheckPermission implements CheckPermissions { 18 | 19 | 20 | @Override 21 | public boolean checkPermission(CheckTokenEntity checkTokenEntity) { 22 | return false; 23 | } 24 | } 25 | */ 26 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/security/CustomRedisTokenStore.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.security; 2 | 3 | import org.springframework.data.redis.connection.RedisConnection; 4 | import org.springframework.data.redis.connection.RedisConnectionFactory; 5 | import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken; 6 | import org.springframework.security.oauth2.common.OAuth2AccessToken; 7 | import org.springframework.security.oauth2.common.OAuth2RefreshToken; 8 | import org.springframework.security.oauth2.provider.OAuth2Authentication; 9 | import org.springframework.security.oauth2.provider.token.AuthenticationKeyGenerator; 10 | import org.springframework.security.oauth2.provider.token.DefaultAuthenticationKeyGenerator; 11 | import org.springframework.security.oauth2.provider.token.TokenStore; 12 | import org.springframework.security.oauth2.provider.token.store.redis.JdkSerializationStrategy; 13 | import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStoreSerializationStrategy; 14 | 15 | import java.util.*; 16 | 17 | /** 18 | * CustomRedisStore 19 | * 20 | * @author xuan 21 | * @date 2018/9/2 22 | */ 23 | public class CustomRedisTokenStore implements TokenStore { 24 | private static final String ACCESS = "access:"; 25 | private static final String AUTH_TO_ACCESS = "auth_to_access:"; 26 | private static final String AUTH = "auth:"; 27 | private static final String REFRESH_AUTH = "refresh_auth:"; 28 | private static final String ACCESS_TO_REFRESH = "access_to_refresh:"; 29 | private static final String REFRESH = "refresh:"; 30 | private static final String REFRESH_TO_ACCESS = "refresh_to_access:"; 31 | private static final String CLIENT_ID_TO_ACCESS = "client_id_to_access:"; 32 | private static final String UNAME_TO_ACCESS = "uname_to_access:"; 33 | 34 | private final RedisConnectionFactory connectionFactory; 35 | private AuthenticationKeyGenerator authenticationKeyGenerator = new DefaultAuthenticationKeyGenerator(); 36 | private RedisTokenStoreSerializationStrategy serializationStrategy = new JdkSerializationStrategy(); 37 | 38 | private String prefix = ""; 39 | 40 | public CustomRedisTokenStore(RedisConnectionFactory connectionFactory) { 41 | this.connectionFactory = connectionFactory; 42 | } 43 | 44 | public void setAuthenticationKeyGenerator(AuthenticationKeyGenerator authenticationKeyGenerator) { 45 | this.authenticationKeyGenerator = authenticationKeyGenerator; 46 | } 47 | 48 | public void setSerializationStrategy(RedisTokenStoreSerializationStrategy serializationStrategy) { 49 | this.serializationStrategy = serializationStrategy; 50 | } 51 | 52 | public void setPrefix(String prefix) { 53 | this.prefix = prefix; 54 | } 55 | 56 | private RedisConnection getConnection() { 57 | return connectionFactory.getConnection(); 58 | } 59 | 60 | private byte[] serialize(Object object) { 61 | return serializationStrategy.serialize(object); 62 | } 63 | 64 | private byte[] serializeKey(String object) { 65 | return serialize(prefix + object); 66 | } 67 | 68 | private OAuth2AccessToken deserializeAccessToken(byte[] bytes) { 69 | return serializationStrategy.deserialize(bytes, OAuth2AccessToken.class); 70 | } 71 | 72 | private OAuth2Authentication deserializeAuthentication(byte[] bytes) { 73 | return serializationStrategy.deserialize(bytes, OAuth2Authentication.class); 74 | } 75 | 76 | private OAuth2RefreshToken deserializeRefreshToken(byte[] bytes) { 77 | return serializationStrategy.deserialize(bytes, OAuth2RefreshToken.class); 78 | } 79 | 80 | private byte[] serialize(String string) { 81 | return serializationStrategy.serialize(string); 82 | } 83 | 84 | private String deserializeString(byte[] bytes) { 85 | return serializationStrategy.deserializeString(bytes); 86 | } 87 | 88 | @Override 89 | public OAuth2AccessToken getAccessToken(OAuth2Authentication authentication) { 90 | String key = authenticationKeyGenerator.extractKey(authentication); 91 | byte[] serializedKey = serializeKey(AUTH_TO_ACCESS + key); 92 | byte[] bytes = null; 93 | RedisConnection conn = getConnection(); 94 | try { 95 | bytes = conn.get(serializedKey); 96 | } finally { 97 | conn.close(); 98 | } 99 | OAuth2AccessToken accessToken = deserializeAccessToken(bytes); 100 | if (accessToken != null) { 101 | OAuth2Authentication storedAuthentication = readAuthentication(accessToken.getValue()); 102 | if ((storedAuthentication == null || !key.equals(authenticationKeyGenerator.extractKey(storedAuthentication)))) { 103 | // Keep the stores consistent (maybe the same user is 104 | // represented by this authentication but the details have 105 | // changed) 106 | storeAccessToken(accessToken, authentication); 107 | } 108 | 109 | } 110 | return accessToken; 111 | } 112 | 113 | @Override 114 | public OAuth2Authentication readAuthentication(OAuth2AccessToken token) { 115 | return readAuthentication(token.getValue()); 116 | } 117 | 118 | @Override 119 | public OAuth2Authentication readAuthentication(String token) { 120 | byte[] bytes = null; 121 | RedisConnection conn = getConnection(); 122 | try { 123 | bytes = conn.get(serializeKey(AUTH + token)); 124 | } finally { 125 | conn.close(); 126 | } 127 | OAuth2Authentication auth = deserializeAuthentication(bytes); 128 | return auth; 129 | } 130 | 131 | @Override 132 | public OAuth2Authentication readAuthenticationForRefreshToken(OAuth2RefreshToken token) { 133 | return readAuthenticationForRefreshToken(token.getValue()); 134 | } 135 | 136 | public OAuth2Authentication readAuthenticationForRefreshToken(String token) { 137 | RedisConnection conn = getConnection(); 138 | try { 139 | byte[] bytes = conn.get(serializeKey(REFRESH_AUTH + token)); 140 | OAuth2Authentication auth = deserializeAuthentication(bytes); 141 | return auth; 142 | } finally { 143 | conn.close(); 144 | } 145 | } 146 | 147 | @Override 148 | public void storeAccessToken(OAuth2AccessToken token, OAuth2Authentication authentication) { 149 | byte[] serializedAccessToken = serialize(token); 150 | byte[] serializedAuth = serialize(authentication); 151 | byte[] accessKey = serializeKey(ACCESS + token.getValue()); 152 | byte[] authKey = serializeKey(AUTH + token.getValue()); 153 | byte[] authToAccessKey = serializeKey(AUTH_TO_ACCESS + authenticationKeyGenerator.extractKey(authentication)); 154 | byte[] approvalKey = serializeKey(UNAME_TO_ACCESS + getApprovalKey(authentication)); 155 | byte[] clientId = serializeKey(CLIENT_ID_TO_ACCESS + authentication.getOAuth2Request().getClientId()); 156 | 157 | RedisConnection conn = getConnection(); 158 | try { 159 | conn.openPipeline(); 160 | conn.stringCommands().set(accessKey, serializedAccessToken); 161 | conn.stringCommands().set(authKey, serializedAuth); 162 | conn.stringCommands().set(authToAccessKey, serializedAccessToken); 163 | if (!authentication.isClientOnly()) { 164 | conn.rPush(approvalKey, serializedAccessToken); 165 | } 166 | conn.rPush(clientId, serializedAccessToken); 167 | if (token.getExpiration() != null) { 168 | int seconds = token.getExpiresIn(); 169 | conn.expire(accessKey, seconds); 170 | conn.expire(authKey, seconds); 171 | conn.expire(authToAccessKey, seconds); 172 | conn.expire(clientId, seconds); 173 | conn.expire(approvalKey, seconds); 174 | } 175 | OAuth2RefreshToken refreshToken = token.getRefreshToken(); 176 | if (refreshToken != null && refreshToken.getValue() != null) { 177 | byte[] refresh = serialize(token.getRefreshToken().getValue()); 178 | byte[] auth = serialize(token.getValue()); 179 | byte[] refreshToAccessKey = serializeKey(REFRESH_TO_ACCESS + token.getRefreshToken().getValue()); 180 | conn.stringCommands().set(refreshToAccessKey, auth); 181 | byte[] accessToRefreshKey = serializeKey(ACCESS_TO_REFRESH + token.getValue()); 182 | conn.stringCommands().set(accessToRefreshKey, refresh); 183 | if (refreshToken instanceof ExpiringOAuth2RefreshToken) { 184 | ExpiringOAuth2RefreshToken expiringRefreshToken = (ExpiringOAuth2RefreshToken) refreshToken; 185 | Date expiration = expiringRefreshToken.getExpiration(); 186 | if (expiration != null) { 187 | int seconds = Long.valueOf((expiration.getTime() - System.currentTimeMillis()) / 1000L) 188 | .intValue(); 189 | conn.expire(refreshToAccessKey, seconds); 190 | conn.expire(accessToRefreshKey, seconds); 191 | } 192 | } 193 | } 194 | conn.closePipeline(); 195 | } finally { 196 | conn.close(); 197 | } 198 | } 199 | 200 | private static String getApprovalKey(OAuth2Authentication authentication) { 201 | String userName = authentication.getUserAuthentication() == null ? "" 202 | : authentication.getUserAuthentication().getName(); 203 | return getApprovalKey(authentication.getOAuth2Request().getClientId(), userName); 204 | } 205 | 206 | private static String getApprovalKey(String clientId, String userName) { 207 | return clientId + (userName == null ? "" : ":" + userName); 208 | } 209 | 210 | @Override 211 | public void removeAccessToken(OAuth2AccessToken accessToken) { 212 | removeAccessToken(accessToken.getValue()); 213 | } 214 | 215 | @Override 216 | public OAuth2AccessToken readAccessToken(String tokenValue) { 217 | byte[] key = serializeKey(ACCESS + tokenValue); 218 | byte[] bytes = null; 219 | RedisConnection conn = getConnection(); 220 | try { 221 | bytes = conn.get(key); 222 | } finally { 223 | conn.close(); 224 | } 225 | OAuth2AccessToken accessToken = deserializeAccessToken(bytes); 226 | return accessToken; 227 | } 228 | 229 | public void removeAccessToken(String tokenValue) { 230 | byte[] accessKey = serializeKey(ACCESS + tokenValue); 231 | byte[] authKey = serializeKey(AUTH + tokenValue); 232 | byte[] accessToRefreshKey = serializeKey(ACCESS_TO_REFRESH + tokenValue); 233 | RedisConnection conn = getConnection(); 234 | try { 235 | conn.openPipeline(); 236 | conn.get(accessKey); 237 | conn.get(authKey); 238 | conn.del(accessKey); 239 | conn.del(accessToRefreshKey); 240 | // Don't remove the refresh token - it's up to the caller to do that 241 | conn.del(authKey); 242 | List results = conn.closePipeline(); 243 | byte[] access = (byte[]) results.get(0); 244 | byte[] auth = (byte[]) results.get(1); 245 | 246 | OAuth2Authentication authentication = deserializeAuthentication(auth); 247 | if (authentication != null) { 248 | String key = authenticationKeyGenerator.extractKey(authentication); 249 | byte[] authToAccessKey = serializeKey(AUTH_TO_ACCESS + key); 250 | byte[] unameKey = serializeKey(UNAME_TO_ACCESS + getApprovalKey(authentication)); 251 | byte[] clientId = serializeKey(CLIENT_ID_TO_ACCESS + authentication.getOAuth2Request().getClientId()); 252 | conn.openPipeline(); 253 | conn.del(authToAccessKey); 254 | conn.lRem(unameKey, 1, access); 255 | conn.lRem(clientId, 1, access); 256 | conn.del(serialize(ACCESS + key)); 257 | conn.closePipeline(); 258 | } 259 | } finally { 260 | conn.close(); 261 | } 262 | } 263 | 264 | @Override 265 | public void storeRefreshToken(OAuth2RefreshToken refreshToken, OAuth2Authentication authentication) { 266 | byte[] refreshKey = serializeKey(REFRESH + refreshToken.getValue()); 267 | byte[] refreshAuthKey = serializeKey(REFRESH_AUTH + refreshToken.getValue()); 268 | byte[] serializedRefreshToken = serialize(refreshToken); 269 | RedisConnection conn = getConnection(); 270 | try { 271 | conn.openPipeline(); 272 | conn.stringCommands().set(refreshKey, serializedRefreshToken); 273 | conn.stringCommands().set(refreshAuthKey, serialize(authentication)); 274 | if (refreshToken instanceof ExpiringOAuth2RefreshToken) { 275 | ExpiringOAuth2RefreshToken expiringRefreshToken = (ExpiringOAuth2RefreshToken) refreshToken; 276 | Date expiration = expiringRefreshToken.getExpiration(); 277 | if (expiration != null) { 278 | int seconds = Long.valueOf((expiration.getTime() - System.currentTimeMillis()) / 1000L) 279 | .intValue(); 280 | conn.expire(refreshKey, seconds); 281 | conn.expire(refreshAuthKey, seconds); 282 | } 283 | } 284 | conn.closePipeline(); 285 | } finally { 286 | conn.close(); 287 | } 288 | } 289 | 290 | @Override 291 | public OAuth2RefreshToken readRefreshToken(String tokenValue) { 292 | byte[] key = serializeKey(REFRESH + tokenValue); 293 | byte[] bytes = null; 294 | RedisConnection conn = getConnection(); 295 | try { 296 | bytes = conn.get(key); 297 | } finally { 298 | conn.close(); 299 | } 300 | OAuth2RefreshToken refreshToken = deserializeRefreshToken(bytes); 301 | return refreshToken; 302 | } 303 | 304 | @Override 305 | public void removeRefreshToken(OAuth2RefreshToken refreshToken) { 306 | removeRefreshToken(refreshToken.getValue()); 307 | } 308 | 309 | public void removeRefreshToken(String tokenValue) { 310 | byte[] refreshKey = serializeKey(REFRESH + tokenValue); 311 | byte[] refreshAuthKey = serializeKey(REFRESH_AUTH + tokenValue); 312 | byte[] refresh2AccessKey = serializeKey(REFRESH_TO_ACCESS + tokenValue); 313 | byte[] access2RefreshKey = serializeKey(ACCESS_TO_REFRESH + tokenValue); 314 | RedisConnection conn = getConnection(); 315 | try { 316 | conn.openPipeline(); 317 | conn.del(refreshKey); 318 | conn.del(refreshAuthKey); 319 | conn.del(refresh2AccessKey); 320 | conn.del(access2RefreshKey); 321 | conn.closePipeline(); 322 | } finally { 323 | conn.close(); 324 | } 325 | } 326 | 327 | @Override 328 | public void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) { 329 | removeAccessTokenUsingRefreshToken(refreshToken.getValue()); 330 | } 331 | 332 | private void removeAccessTokenUsingRefreshToken(String refreshToken) { 333 | byte[] key = serializeKey(REFRESH_TO_ACCESS + refreshToken); 334 | List results = null; 335 | RedisConnection conn = getConnection(); 336 | try { 337 | conn.openPipeline(); 338 | conn.get(key); 339 | conn.del(key); 340 | results = conn.closePipeline(); 341 | } finally { 342 | conn.close(); 343 | } 344 | if (results == null) { 345 | return; 346 | } 347 | byte[] bytes = (byte[]) results.get(0); 348 | String accessToken = deserializeString(bytes); 349 | if (accessToken != null) { 350 | removeAccessToken(accessToken); 351 | } 352 | } 353 | 354 | @Override 355 | public Collection findTokensByClientIdAndUserName(String clientId, String userName) { 356 | byte[] approvalKey = serializeKey(UNAME_TO_ACCESS + getApprovalKey(clientId, userName)); 357 | List byteList = null; 358 | RedisConnection conn = getConnection(); 359 | try { 360 | byteList = conn.lRange(approvalKey, 0, -1); 361 | } finally { 362 | conn.close(); 363 | } 364 | if (byteList == null || byteList.size() == 0) { 365 | return Collections. emptySet(); 366 | } 367 | List accessTokens = new ArrayList(byteList.size()); 368 | for (byte[] bytes : byteList) { 369 | OAuth2AccessToken accessToken = deserializeAccessToken(bytes); 370 | accessTokens.add(accessToken); 371 | } 372 | return Collections. unmodifiableCollection(accessTokens); 373 | } 374 | 375 | @Override 376 | public Collection findTokensByClientId(String clientId) { 377 | byte[] key = serializeKey(CLIENT_ID_TO_ACCESS + clientId); 378 | List byteList = null; 379 | RedisConnection conn = getConnection(); 380 | try { 381 | byteList = conn.lRange(key, 0, -1); 382 | } finally { 383 | conn.close(); 384 | } 385 | if (byteList == null || byteList.size() == 0) { 386 | return Collections. emptySet(); 387 | } 388 | List accessTokens = new ArrayList(byteList.size()); 389 | for (byte[] bytes : byteList) { 390 | OAuth2AccessToken accessToken = deserializeAccessToken(bytes); 391 | accessTokens.add(accessToken); 392 | } 393 | return Collections. unmodifiableCollection(accessTokens); 394 | } 395 | } 396 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/security/CustomTokenEnhancer.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.security; 2 | 3 | import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken; 4 | import org.springframework.security.oauth2.common.OAuth2AccessToken; 5 | import org.springframework.security.oauth2.provider.OAuth2Authentication; 6 | import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter; 7 | 8 | import java.io.ObjectStreamException; 9 | import java.io.Serializable; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | /** 14 | * Created by keets on 2017/8/5. 15 | */ 16 | public class CustomTokenEnhancer extends JwtAccessTokenConverter implements Serializable { 17 | private static int authenticateCodeExpiresTime = 10 * 60; 18 | 19 | private static final String TOKEN_SEG_USER_ID = "X-AOHO-UserId"; 20 | private static final String TOKEN_SEG_CLIENT = "X-AOHO-ClientId"; 21 | 22 | @Override 23 | public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, 24 | OAuth2Authentication authentication) { 25 | CustomUserDetails userDetails = (CustomUserDetails) authentication.getPrincipal(); 26 | authentication.getUserAuthentication().getPrincipal(); 27 | Map info = new HashMap<>(); 28 | info.put(TOKEN_SEG_USER_ID, userDetails.getUserId()); 29 | 30 | DefaultOAuth2AccessToken customAccessToken = new DefaultOAuth2AccessToken(accessToken); 31 | customAccessToken.setAdditionalInformation(info); 32 | 33 | OAuth2AccessToken enhancedToken = super.enhance(customAccessToken, authentication); 34 | enhancedToken.getAdditionalInformation().put(TOKEN_SEG_CLIENT, userDetails.getClientId()); 35 | return enhancedToken; 36 | } 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/security/CustomUserDetails.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.security; 2 | 3 | import org.springframework.security.core.GrantedAuthority; 4 | import org.springframework.security.core.userdetails.UserDetails; 5 | 6 | import java.util.Collection; 7 | 8 | /** 9 | * @author keets 10 | * @date 2017/8/5 11 | */ 12 | public class CustomUserDetails implements UserDetails { 13 | static final long serialVersionUID = -7588980448693010399L; 14 | private String username; 15 | 16 | private String password; 17 | 18 | private boolean enabled = true; 19 | 20 | private String userId; 21 | 22 | private String clientId; 23 | 24 | private Collection authorities; 25 | 26 | public String getClientId() { 27 | return clientId; 28 | } 29 | 30 | public void setClientId(String clientId) { 31 | this.clientId = clientId; 32 | } 33 | 34 | public String getUserId() { 35 | return userId; 36 | } 37 | 38 | public void setUsername(String username) { 39 | this.username = username; 40 | } 41 | 42 | public void setPassword(String password) { 43 | this.password = password; 44 | } 45 | 46 | 47 | public void setEnabled(boolean enabled) { 48 | this.enabled = enabled; 49 | } 50 | 51 | public void setUserId(String userId) { 52 | this.userId = userId; 53 | } 54 | 55 | 56 | public void setAuthorities(Collection authorities) { 57 | this.authorities = authorities; 58 | } 59 | 60 | @Override 61 | public Collection getAuthorities() { 62 | return authorities; 63 | } 64 | 65 | @Override 66 | public String getPassword() { 67 | return this.password; 68 | } 69 | 70 | @Override 71 | public String getUsername() { 72 | return this.username; 73 | } 74 | 75 | @Override 76 | public boolean isAccountNonExpired() { 77 | return true; 78 | } 79 | 80 | @Override 81 | public boolean isAccountNonLocked() { 82 | return true; 83 | } 84 | 85 | @Override 86 | public boolean isCredentialsNonExpired() { 87 | return true; 88 | } 89 | 90 | @Override 91 | public boolean isEnabled() { 92 | return enabled; 93 | } 94 | 95 | public static class CustomUserDetailsBuilder { 96 | private CustomUserDetails userDetails = new CustomUserDetails(); 97 | 98 | public CustomUserDetailsBuilder withUsername(String username) { 99 | userDetails.setUsername(username); 100 | userDetails.setAuthorities(null); 101 | return this; 102 | } 103 | 104 | public CustomUserDetailsBuilder withPassword(String password) { 105 | userDetails.setPassword(password); 106 | return this; 107 | } 108 | 109 | public CustomUserDetailsBuilder withClientId(String clientId) { 110 | userDetails.setClientId(clientId); 111 | return this; 112 | } 113 | 114 | public CustomUserDetailsBuilder withUserId(String userId) { 115 | userDetails.setUserId(userId); 116 | return this; 117 | } 118 | 119 | public CustomUserDetails build() { 120 | return userDetails; 121 | } 122 | } 123 | 124 | } 125 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/security/filter/CustomLogoutHandler.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.security.filter; 2 | 3 | import org.apache.commons.lang3.StringUtils; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.security.core.Authentication; 8 | import org.springframework.security.oauth2.common.OAuth2AccessToken; 9 | import org.springframework.security.oauth2.common.OAuth2RefreshToken; 10 | import org.springframework.security.oauth2.common.exceptions.BadClientCredentialsException; 11 | import org.springframework.security.oauth2.provider.token.TokenStore; 12 | import org.springframework.security.web.authentication.logout.LogoutHandler; 13 | import org.springframework.util.Assert; 14 | 15 | import javax.servlet.http.HttpServletRequest; 16 | import javax.servlet.http.HttpServletResponse; 17 | 18 | /** 19 | * @author keets 20 | * @date 2017/10/17 21 | */ 22 | public class CustomLogoutHandler implements LogoutHandler { 23 | 24 | private static final Logger LOGGER = LoggerFactory.getLogger(CustomLogoutHandler.class); 25 | 26 | 27 | @Autowired 28 | private TokenStore tokenStore; 29 | 30 | @Override 31 | public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) { 32 | Assert.notNull(tokenStore, "tokenStore must be set"); 33 | String token = request.getHeader("Authorization"); 34 | Assert.hasText(token, "token must be set"); 35 | if (isJwtBearerToken(token)) { 36 | token = token.substring(6).trim(); 37 | OAuth2AccessToken existingAccessToken = tokenStore.readAccessToken(token); 38 | OAuth2RefreshToken refreshToken; 39 | if (existingAccessToken != null) { 40 | if (existingAccessToken.getRefreshToken() != null) { 41 | LOGGER.info("remove refreshToken!", existingAccessToken.getRefreshToken()); 42 | refreshToken = existingAccessToken.getRefreshToken(); 43 | tokenStore.removeRefreshToken(refreshToken); 44 | } 45 | LOGGER.info("remove existingAccessToken!", existingAccessToken); 46 | tokenStore.removeAccessToken(existingAccessToken); 47 | } 48 | return; 49 | } else { 50 | throw new BadClientCredentialsException(); 51 | } 52 | 53 | } 54 | 55 | 56 | private boolean isJwtBearerToken(String token) { 57 | return StringUtils.countMatches(token, ".") == 2 && (token.startsWith("Bearer") || token.startsWith("bearer")); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/security/filter/CustomSecurityFilter.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.security.filter; 2 | 3 | 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | import org.springframework.beans.factory.annotation.Autowired; 7 | import org.springframework.security.access.AccessDeniedException; 8 | import org.springframework.security.access.SecurityMetadataSource; 9 | import org.springframework.security.access.intercept.AbstractSecurityInterceptor; 10 | import org.springframework.security.access.intercept.InterceptorStatusToken; 11 | import org.springframework.security.authentication.AuthenticationManager; 12 | import org.springframework.security.web.FilterInvocation; 13 | 14 | import javax.annotation.PostConstruct; 15 | import javax.servlet.*; 16 | import java.io.IOException; 17 | 18 | 19 | public class CustomSecurityFilter extends AbstractSecurityInterceptor implements Filter { 20 | private Logger logger = LoggerFactory.getLogger(CustomSecurityFilter.class); 21 | 22 | @Autowired 23 | SecureResourceFilterInvocationDefinitionSource invocationSource; 24 | 25 | @Autowired 26 | private AuthenticationManager authenticationManager; 27 | 28 | @Autowired 29 | SecurityAccessDecisionManager decisionManager; 30 | 31 | @PostConstruct 32 | public void init() { 33 | super.setAccessDecisionManager(decisionManager); 34 | super.setAuthenticationManager(authenticationManager); 35 | } 36 | 37 | @Override 38 | public void init(FilterConfig filterConfig) throws ServletException { 39 | logger.info("init in Security "); 40 | } 41 | 42 | 43 | @Override 44 | public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { 45 | logger.info("doFilter in Security "); 46 | 47 | FilterInvocation fi = new FilterInvocation(servletRequest, servletResponse, filterChain); 48 | //beforeInvocation会调用SecureResourceDataSource中的逻辑 49 | InterceptorStatusToken token = super.beforeInvocation(fi); 50 | try { 51 | fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); 52 | 53 | //执行下一个拦截器 54 | } finally { 55 | 56 | logger.info("through filter"); 57 | super.afterInvocation(token, null); 58 | //throw new AccessDeniedException("no right"); 59 | 60 | } 61 | 62 | } 63 | 64 | @Override 65 | public void destroy() { 66 | 67 | } 68 | 69 | @Override 70 | public Class getSecureObjectClass() { 71 | return FilterInvocation.class; 72 | } 73 | 74 | @Override 75 | public SecurityMetadataSource obtainSecurityMetadataSource() { 76 | return invocationSource; 77 | } 78 | 79 | 80 | } 81 | 82 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/security/filter/SecureResourceFilterInvocationDefinitionSource.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.security.filter; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.beans.factory.InitializingBean; 6 | import org.springframework.security.access.ConfigAttribute; 7 | import org.springframework.security.access.SecurityConfig; 8 | import org.springframework.security.web.FilterInvocation; 9 | import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; 10 | import org.springframework.stereotype.Component; 11 | import org.springframework.util.AntPathMatcher; 12 | import org.springframework.util.PathMatcher; 13 | 14 | import java.util.*; 15 | 16 | /** 17 | * @author keets 18 | */ 19 | @Component 20 | public class SecureResourceFilterInvocationDefinitionSource implements FilterInvocationSecurityMetadataSource, InitializingBean { 21 | private Logger logger = LoggerFactory.getLogger(SecureResourceFilterInvocationDefinitionSource.class); 22 | 23 | private PathMatcher matcher; 24 | 25 | private static Map> map = new HashMap<>(); 26 | 27 | @Override 28 | public Collection getAttributes(Object o) throws IllegalArgumentException { 29 | logger.info("getAttributes"); 30 | //应该做instanceof 31 | FilterInvocation filterInvocation = (FilterInvocation) o; 32 | //String method = filterInvocation.getHttpRequest().getMethod(); 33 | String requestURI = filterInvocation.getRequestUrl(); 34 | //循环资源路径,当访问的Url和资源路径url匹配时,返回该Url所需要的权限 35 | for (Iterator>> iter = map.entrySet().iterator(); iter.hasNext(); ) { 36 | Map.Entry> entry = iter.next(); 37 | String url = entry.getKey(); 38 | 39 | if (matcher.match(url, requestURI)) { 40 | return map.get(requestURI); 41 | } 42 | } 43 | return null; 44 | } 45 | 46 | @Override 47 | public Collection getAllConfigAttributes() { 48 | return null; 49 | } 50 | 51 | @Override 52 | public boolean supports(Class aClass) { 53 | return true; 54 | } 55 | 56 | @Override 57 | public void afterPropertiesSet() throws Exception { 58 | logger.info("afterPropertiesSet"); 59 | //用来匹配访问资源路径 60 | this.matcher = new AntPathMatcher(); 61 | //可以有多个权限 62 | Collection atts = new ArrayList<>(); 63 | ConfigAttribute c1 = new SecurityConfig("ROLE_USER"); 64 | atts.add(c1); 65 | map.put("/api/permission/apiPermissions", atts); 66 | } 67 | } 68 | 69 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/security/filter/SecurityAccessDecisionManager.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.security.filter; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | import org.springframework.security.access.AccessDecisionManager; 6 | import org.springframework.security.access.AccessDeniedException; 7 | import org.springframework.security.access.ConfigAttribute; 8 | import org.springframework.security.authentication.InsufficientAuthenticationException; 9 | import org.springframework.security.core.Authentication; 10 | import org.springframework.security.core.GrantedAuthority; 11 | import org.springframework.stereotype.Component; 12 | 13 | import java.util.Collection; 14 | import java.util.Iterator; 15 | 16 | /** 17 | * @author keets 18 | */ 19 | @Component 20 | public class SecurityAccessDecisionManager implements AccessDecisionManager { 21 | private Logger logger = LoggerFactory.getLogger(SecurityAccessDecisionManager.class); 22 | 23 | /** 24 | * @param authentication 用户权限 25 | * @param o url 26 | * @param collection 所需要的权限 27 | * @throws AccessDeniedException 28 | * @throws InsufficientAuthenticationException 29 | */ 30 | @Override 31 | public void decide(Authentication authentication, Object o, Collection collection) throws AccessDeniedException, InsufficientAuthenticationException { 32 | logger.info("decide url and permission"); 33 | if (collection == null) { 34 | return; 35 | } 36 | 37 | Iterator ite = collection.iterator(); 38 | //判断用户所拥有的权限,是否符合对应的Url权限,如果实现了UserDetailsService,则用户权限是loadUserByUsername返回用户所对应的权限 39 | while (ite.hasNext()) { 40 | ConfigAttribute ca = ite.next(); 41 | String needRole = ca.getAttribute(); 42 | for (GrantedAuthority ga : authentication.getAuthorities()) { 43 | logger.info("GrantedAuthority: {}", ga); 44 | if (needRole.equals(ga.getAuthority())) { 45 | return; 46 | } 47 | } 48 | } 49 | logger.error("AccessDecisionManager: no right!"); 50 | throw new AccessDeniedException("no right!"); 51 | } 52 | 53 | @Override 54 | public boolean supports(ConfigAttribute configAttribute) { 55 | return true; 56 | } 57 | 58 | //是否支持FilterInvocation需要将这里的false改为true 59 | @Override 60 | public boolean supports(Class aClass) { 61 | return true; 62 | } 63 | } 64 | 65 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/service/ClientSecretService.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.service; 2 | 3 | import com.blueskykong.auth.dao.ClientSecretDAO; 4 | import com.blueskykong.auth.dto.ApiClientDTO; 5 | import com.blueskykong.auth.entity.ClientSecret; 6 | import com.blueskykong.auth.entity.ClientSecretStatus; 7 | import com.google.common.collect.Lists; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.springframework.stereotype.Service; 10 | 11 | import java.util.List; 12 | import java.util.UUID; 13 | 14 | /** 15 | * @author keets 16 | * @date 2017/10/18 17 | */ 18 | @Service 19 | public class ClientSecretService { 20 | @Autowired 21 | private ClientSecretDAO clientSecretDao; 22 | 23 | public void createClientSecret(ApiClientDTO apiClient) { 24 | ClientSecret clientSecret = new ClientSecret.ClientSecretBuilder() 25 | .withClientId(apiClient.getClientId()) 26 | .withClientSecret(apiClient.getClientSecret()) 27 | .withTenantId(apiClient.getTenantId()) 28 | .withPurpose(apiClient.getPurpose()) 29 | .withStatus(ClientSecretStatus.ACTIVE) 30 | .build(); 31 | clientSecretDao.create(clientSecret); 32 | } 33 | 34 | public ApiClientDTO getClientSecretByClientId(String clientId) { 35 | ClientSecret clientSecret = new ClientSecret.ClientSecretBuilder() 36 | .withClientId(clientId) 37 | .build(); 38 | List results = clientSecretDao.get(clientSecret); 39 | System.out.println(results.size()); 40 | if (results.size() >= 1) { 41 | return convert(results.get(0)); 42 | } 43 | return null; 44 | } 45 | 46 | public List getClientSecretByTenantId(UUID tenantId) { 47 | ClientSecret clientSecret = new ClientSecret.ClientSecretBuilder() 48 | .withTenantId(tenantId) 49 | .build(); 50 | return Lists.transform(clientSecretDao.get(clientSecret), this::convert); 51 | } 52 | 53 | public int updateClientSecret(ApiClientDTO apiClient) { 54 | ClientSecret clientSecret = new ClientSecret.ClientSecretBuilder() 55 | .withClientSecret(apiClient.getClientSecret()) 56 | .withPurpose(apiClient.getPurpose()) 57 | .withStatus(ClientSecretStatus.valueOf(apiClient.getStatus())) 58 | .withClientId(apiClient.getClientId()) 59 | .withTenantId(apiClient.getTenantId()) 60 | .build(); 61 | return clientSecretDao.update(clientSecret); 62 | } 63 | 64 | public int updateClientSecretByTenantId(UUID tenantId, ClientSecretStatus status) { 65 | return clientSecretDao.updateStatusByTenantId(tenantId, status); 66 | } 67 | 68 | public int updateClientSecretByClientId(String clientId, ApiClientDTO apiClient) { 69 | ClientSecretStatus status = ClientSecretStatus.valueOf(apiClient.getStatus()); 70 | return clientSecretDao.updateStatusByClientId(clientId, status); 71 | } 72 | 73 | private ApiClientDTO convert(ClientSecret clientSecret) { 74 | ApiClientDTO apiClient = new ApiClientDTO(); 75 | apiClient.setClientId(clientSecret.getClientId()); 76 | apiClient.setClientSecret(clientSecret.getClientSecret()); 77 | 78 | apiClient.setStatus(clientSecret.getStatus().name()); 79 | /* apiClient.setStatus(clientSecret.getStatus().toString()); 80 | apiClient.setPurpose(clientSecret.getPurpose()); 81 | apiClient.setUserId(clientSecret.getUserId());*/ 82 | return apiClient; 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/service/SecurityService.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.service; 2 | 3 | import com.blueskykong.auth.dao.PermissionDAO; 4 | import com.blueskykong.auth.dao.RoleDAO; 5 | import com.blueskykong.auth.dao.RolePermissionDAO; 6 | import com.blueskykong.auth.dao.UserAccessDAO; 7 | import com.blueskykong.auth.dao.UserRoleDAO; 8 | import com.blueskykong.auth.dto.DefaultRole; 9 | import com.blueskykong.auth.dto.DefaultRoles; 10 | import com.blueskykong.auth.dto.RolePermissionDTO; 11 | import com.blueskykong.auth.dto.UserRoleDTO; 12 | import com.blueskykong.auth.entity.Permission; 13 | import com.blueskykong.auth.entity.Role; 14 | import com.blueskykong.auth.entity.RolePermission; 15 | import com.blueskykong.auth.entity.UserAccess; 16 | import com.blueskykong.auth.entity.UserRole; 17 | import org.slf4j.Logger; 18 | import org.slf4j.LoggerFactory; 19 | import org.springframework.beans.factory.annotation.Autowired; 20 | import org.springframework.stereotype.Service; 21 | import org.springframework.transaction.annotation.Transactional; 22 | 23 | import java.util.ArrayList; 24 | import java.util.HashMap; 25 | import java.util.List; 26 | import java.util.Map; 27 | import java.util.UUID; 28 | 29 | /** 30 | * @author keets 31 | * @date 2017/11/22 32 | */ 33 | @Service 34 | @Transactional 35 | public class SecurityService { 36 | 37 | private static final Logger LOGGER = LoggerFactory.getLogger(SecurityService.class); 38 | 39 | @Autowired 40 | private PermissionDAO permissionDAO; 41 | 42 | @Autowired 43 | private UserAccessDAO userAccessDAO; 44 | 45 | @Autowired 46 | private RoleDAO roleDAO; 47 | 48 | @Autowired 49 | private RolePermissionDAO rolePermissionDAO; 50 | 51 | @Autowired 52 | private UserRoleDAO userRoleDAO; 53 | 54 | public List getPermissionListByUserId(String userId) { 55 | Map map = new HashMap<>(); 56 | map.put("userId", UUID.fromString(userId)); 57 | return permissionDAO.getPermissionList(map); 58 | } 59 | 60 | public List getUserAccessList(String userId) { 61 | return userAccessDAO.securitySelectByUserId(UUID.fromString(userId)); 62 | } 63 | 64 | public void revokeRole(UUID userId) { 65 | deleteAccessRole(userId); 66 | } 67 | 68 | public List getRolePermissionsByUserId(UUID userId) { 69 | List rolePermissionDTOList = getRolesByUserId(userId); 70 | return rolePermissionDTOList; 71 | } 72 | 73 | public void addUserAccess(UUID userId, Integer accesslevel) { 74 | UserAccess record = new UserAccess(); 75 | record.setUserId(userId); 76 | record.setAccessLevel(accesslevel); 77 | userAccessDAO.securityInsertRecord(record); 78 | } 79 | 80 | public void createUserRoleAccesss(UUID userId, DefaultRole role) { 81 | addUserAccess(userId, 0); 82 | saveUserRole(userId, role); 83 | 84 | if (DefaultRoles.MASTER_ADMIN.getId().equals(role.getId())) { 85 | addUserAccess(userId, 1); 86 | } 87 | } 88 | 89 | public void saveUserRole(UUID userId, DefaultRole role) { 90 | UserRole UserRole = new UserRole.UserRoleBuilder() 91 | .withUserId(userId) 92 | .withRoleId(role.getId()).build(); 93 | userRoleDAO.insertUtRole(UserRole); 94 | } 95 | 96 | 97 | public List getRolesByUserId(UUID userId) { 98 | 99 | List userTenantRoleList = userRoleDAO.selectByUserId(userId); 100 | List roleList = new ArrayList<>(); 101 | List result = new ArrayList<>(); 102 | for (int i = 0; i < userTenantRoleList.size(); i++) { 103 | UUID roleId = userTenantRoleList.get(i).getRoleId(); 104 | roleList.add(roleDAO.selectById(roleId)); 105 | } 106 | //process can be optimized,may be in sql-view not multi queries in sql 107 | for (int i = 0; i < roleList.size(); i++) { 108 | RolePermissionDTO rolePermissionDTO = new RolePermissionDTO(); 109 | rolePermissionDTO.setRelationId(userTenantRoleList.get(i).getId()); 110 | rolePermissionDTO.setRoleId(roleList.get(i).getId()); 111 | rolePermissionDTO.setName(roleList.get(i).getName()); 112 | rolePermissionDTO.setDescription(roleList.get(i).getDescription()); 113 | rolePermissionDTO.setUpdateTime(roleList.get(i).getUpdateTime()); 114 | List rolePermissionList = rolePermissionDAO.selectByRoleId(roleList.get(i).getId()); 115 | List permissionList = new ArrayList<>(); 116 | for (int j = 0; j < rolePermissionList.size(); j++) { 117 | UUID pId = rolePermissionList.get(j).getPermissionId(); 118 | permissionList.add(permissionDAO.selectById(pId)); 119 | } 120 | rolePermissionDTO.setPermissions(permissionList); 121 | result.add(rolePermissionDTO); 122 | } 123 | return result; 124 | } 125 | 126 | public List getUserRoleList(UUID userId) { 127 | return userRoleDAO.selectUserRoleList(userId); 128 | } 129 | 130 | public void deleteAccessRole(UUID userId) { 131 | userRoleDAO.deleteByUserId(userId); 132 | userAccessDAO.deleteByUserId(userId); 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/utils/JsonUtil.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.utils; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | 5 | /** 6 | * Created by keets on 2017/1/17. 7 | */ 8 | public class JsonUtil { 9 | /** 10 | * Json字符串转对象 11 | * @param 12 | * @param jsonStr 13 | * @param clazz 14 | * @return 15 | * @throws Exception 16 | */ 17 | public static T jsonStrToBean(String jsonStr, Class clazz) throws Exception { 18 | ObjectMapper mapper = new ObjectMapper(); 19 | return mapper.readValue(jsonStr, clazz); 20 | } 21 | 22 | /** 23 | * 对象转Json字符串 24 | * @param bean 25 | * @return 26 | * @throws Exception 27 | */ 28 | public static String beanToJsonStr(Object bean) throws Exception { 29 | ObjectMapper mapper = new ObjectMapper(); 30 | return mapper.writeValueAsString(bean); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/blueskykong/auth/utils/TimestampAdapter.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.utils; 2 | 3 | import com.google.common.base.Throwables; 4 | 5 | import javax.xml.bind.annotation.adapters.XmlAdapter; 6 | import javax.xml.datatype.DatatypeConfigurationException; 7 | import javax.xml.datatype.DatatypeFactory; 8 | import javax.xml.datatype.XMLGregorianCalendar; 9 | import java.sql.Timestamp; 10 | import java.text.DateFormat; 11 | import java.text.SimpleDateFormat; 12 | 13 | public class TimestampAdapter extends XmlAdapter { 14 | private static final DatatypeFactory df; 15 | private static final ThreadLocal simpleDateFormat = new ThreadLocal(){ 16 | @Override 17 | protected DateFormat initialValue() { 18 | return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 19 | } 20 | }; 21 | 22 | static { 23 | try { 24 | df = DatatypeFactory.newInstance(); 25 | } catch (DatatypeConfigurationException e) { 26 | throw Throwables.propagate(e); 27 | } 28 | } 29 | 30 | @Override 31 | public String marshal(Timestamp v) throws Exception { 32 | if (v != null) { 33 | return simpleDateFormat.get().format(v); 34 | } 35 | return null; 36 | } 37 | 38 | @Override 39 | public Timestamp unmarshal(String v) throws Exception { 40 | XMLGregorianCalendar cal = df.newXMLGregorianCalendar(v); 41 | try { 42 | return new Timestamp(cal.toGregorianCalendar().getTimeInMillis()); 43 | } catch (Exception e) { 44 | throw Throwables.propagate(e); 45 | } 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/resources/application.yml: -------------------------------------------------------------------------------- 1 | spring: 2 | flyway: 3 | baseline-on-migrate: true 4 | locations: classpath:db 5 | datasource: 6 | hikari: 7 | connection-test-query: SELECT 1 8 | minimum-idle: 1 9 | maximum-pool-size: 5 10 | pool-name: dbcp1 11 | driver-class-name: com.mysql.jdbc.Driver 12 | url: jdbc:mysql://localhost:3306/auth?autoReconnect=true&useSSL=false 13 | username: ${AUTH_DB_PWD:root} 14 | password: ${AUTH_DB_USER:_123456_} 15 | # schema[0]: classpath:/auth.sql 16 | # initialization-mode: ALWAYS 17 | type: com.zaxxer.hikari.HikariDataSource 18 | redis: 19 | database: 0 20 | host: localhost 21 | port: 6379 22 | 23 | ribbon: 24 | ReadTimeout: 10000 25 | 26 | hystrix: 27 | command: 28 | default: 29 | execution: 30 | isolation: 31 | strategy: THREAD 32 | thread: 33 | timeoutInMilliseconds: 10000 34 | management: 35 | health: 36 | db: 37 | enabled: false 38 | 39 | mybatis: 40 | mapper-locations: classpath:/mybatis/mapper/*Mapper.xml 41 | config-location: classpath:/mybatis/config.xml 42 | 43 | -------------------------------------------------------------------------------- /src/main/resources/bootstrap.yml: -------------------------------------------------------------------------------- 1 | server: 2 | port: 10101 3 | 4 | --- 5 | spring: 6 | profiles: default 7 | application: 8 | name: authserver 9 | -------------------------------------------------------------------------------- /src/main/resources/conf/generatorConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 63 |
64 |
65 |
66 | -------------------------------------------------------------------------------- /src/main/resources/db/V1.0__Base_version.sql: -------------------------------------------------------------------------------- 1 | SET FOREIGN_KEY_CHECKS=0; 2 | 3 | -- ---------------------------- 4 | 5 | -- Table structure for `group_role` 6 | 7 | -- ---------------------------- 8 | 9 | DROP TABLE IF EXISTS `group_role`; 10 | CREATE TABLE `group_role` ( 11 | `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, 12 | `group_id` varchar(36) NOT NULL, 13 | `tenant_id` varchar(36) NOT NULL, 14 | `role_id` varchar(36) NOT NULL, 15 | PRIMARY KEY (`id`), 16 | UNIQUE KEY `id` (`id`) 17 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 18 | 19 | -- ---------------------------- 20 | 21 | -- Records of group_role 22 | 23 | -- ---------------------------- 24 | 25 | 26 | 27 | -- ---------------------------- 28 | 29 | -- Table structure for `oauth_access_token` 30 | 31 | -- ---------------------------- 32 | 33 | DROP TABLE IF EXISTS `oauth_access_token`; 34 | CREATE TABLE `oauth_access_token` ( 35 | `token_id` varchar(255) DEFAULT NULL, 36 | `token` blob, 37 | `authentication_id` varchar(255) DEFAULT NULL, 38 | `user_name` varchar(255) DEFAULT NULL, 39 | `client_id` varchar(255) DEFAULT NULL, 40 | `authentication` blob, 41 | `refresh_token` varchar(255) DEFAULT NULL 42 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 43 | 44 | 45 | -- ---------------------------- 46 | 47 | -- Table structure for `oauth_client_details` 48 | 49 | -- ---------------------------- 50 | 51 | DROP TABLE IF EXISTS `oauth_client_details`; 52 | CREATE TABLE `oauth_client_details` ( 53 | `client_id` varchar(255) NOT NULL, 54 | `resource_ids` varchar(255) DEFAULT NULL, 55 | `client_secret` varchar(255) DEFAULT NULL, 56 | `scope` varchar(255) DEFAULT NULL, 57 | `authorized_grant_types` varchar(255) DEFAULT NULL, 58 | `web_server_redirect_uri` varchar(255) DEFAULT NULL, 59 | `authorities` varchar(255) DEFAULT NULL, 60 | `access_token_validity` int(11) DEFAULT NULL, 61 | `refresh_token_validity` int(11) DEFAULT NULL, 62 | `additional_information` varchar(4096) DEFAULT NULL, 63 | `autoapprove` varchar(255) DEFAULT NULL, 64 | `tenant_id` varchar(36) DEFAULT NULL, 65 | `status` varchar(255) DEFAULT NULL, 66 | `purpose` varchar(255) DEFAULT NULL, 67 | `create_time` timestamp NULL DEFAULT NULL, 68 | `update_time` timestamp NULL DEFAULT NULL, 69 | `create_by` varchar(36) DEFAULT NULL, 70 | `update_by` varchar(36) DEFAULT NULL, 71 | PRIMARY KEY (`client_id`) 72 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 73 | 74 | -- ---------------------------- 75 | 76 | -- Records of oauth_client_details 77 | 78 | -- ---------------------------- 79 | 80 | INSERT INTO `oauth_client_details` VALUES ('frontend', null, '$e0801$65x9sjjnRPuKmqaFn3mICtPYnSWrjE7OB/pKzKTAI4ryhmVoa04cus+9sJcSAFKXZaJ8lcPO1I9H22TZk6EN4A==$o+ZWccaWXSA2t7TxE5VBRvz2W8psujU3RPPvejvNs4U=', 'all', 'password,refresh_token,authorization_code', 'http://localhost:8080', null, null, null, null, null, null, null, null, null, null, null, null); 81 | 82 | -- ---------------------------- 83 | 84 | -- Table structure for `oauth_client_token` 85 | 86 | -- ---------------------------- 87 | 88 | DROP TABLE IF EXISTS `oauth_client_token`; 89 | CREATE TABLE `oauth_client_token` ( 90 | `token_id` varchar(255) DEFAULT NULL, 91 | `token` blob, 92 | `authentication_id` varchar(255) DEFAULT NULL, 93 | `user_name` varchar(255) DEFAULT NULL, 94 | `client_id` varchar(255) DEFAULT NULL 95 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 96 | 97 | -- ---------------------------- 98 | 99 | -- Records of oauth_client_token 100 | 101 | -- ---------------------------- 102 | 103 | 104 | -- ---------------------------- 105 | 106 | -- Table structure for `oauth_code` 107 | 108 | -- ---------------------------- 109 | 110 | DROP TABLE IF EXISTS `oauth_code`; 111 | CREATE TABLE `oauth_code` ( 112 | `code` varchar(255) DEFAULT NULL, 113 | `authentication` blob 114 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 115 | 116 | -- ---------------------------- 117 | 118 | -- Records of oauth_code 119 | 120 | -- ---------------------------- 121 | 122 | 123 | -- ---------------------------- 124 | 125 | -- Table structure for `oauth_refresh_token` 126 | 127 | -- ---------------------------- 128 | 129 | DROP TABLE IF EXISTS `oauth_refresh_token`; 130 | CREATE TABLE `oauth_refresh_token` ( 131 | `token_id` varchar(255) DEFAULT NULL, 132 | `token` blob, 133 | `authentication` blob 134 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 135 | 136 | 137 | -- ---------------------------- 138 | 139 | -- Table structure for `permission` 140 | 141 | -- ---------------------------- 142 | 143 | DROP TABLE IF EXISTS `permission`; 144 | CREATE TABLE `permission` ( 145 | `id` varchar(36) NOT NULL, 146 | `permission` varchar(255) DEFAULT NULL, 147 | `description` varchar(255) DEFAULT NULL, 148 | PRIMARY KEY (`id`), 149 | KEY `permission_index` (`permission`) 150 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 151 | 152 | -- ---------------------------- 153 | 154 | -- Records of permission 155 | 156 | -- ---------------------------- 157 | 158 | 159 | -- ---------------------------- 160 | 161 | -- Table structure for `role` 162 | 163 | -- ---------------------------- 164 | 165 | DROP TABLE IF EXISTS `role`; 166 | CREATE TABLE `role` ( 167 | `id` varchar(36) NOT NULL, 168 | `tenant_id` varchar(36) NOT NULL, 169 | `name` varchar(255) NOT NULL, 170 | `update_time` timestamp NULL DEFAULT NULL, 171 | `description` varchar(255) DEFAULT NULL, 172 | PRIMARY KEY (`id`), 173 | KEY `role_name_desc_index` (`name`,`description`) 174 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 175 | 176 | 177 | -- ---------------------------- 178 | 179 | -- Table structure for `role_permission` 180 | 181 | -- ---------------------------- 182 | 183 | DROP TABLE IF EXISTS `role_permission`; 184 | CREATE TABLE `role_permission` ( 185 | `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, 186 | `role_id` varchar(36) NOT NULL, 187 | `permission_id` varchar(36) NOT NULL, 188 | PRIMARY KEY (`id`), 189 | UNIQUE KEY `id` (`id`) 190 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 191 | 192 | -- ---------------------------- 193 | 194 | -- Records of role_permission 195 | 196 | -- ---------------------------- 197 | 198 | 199 | -- ---------------------------- 200 | 201 | -- Table structure for `security_group` 202 | 203 | -- ---------------------------- 204 | 205 | DROP TABLE IF EXISTS `security_group`; 206 | CREATE TABLE `security_group` ( 207 | `id` varchar(36) NOT NULL, 208 | `tenant_id` varchar(36) NOT NULL, 209 | `name` varchar(255) DEFAULT NULL, 210 | `create_time` timestamp NULL DEFAULT NULL, 211 | `update_time` timestamp NULL DEFAULT NULL, 212 | PRIMARY KEY (`id`,`tenant_id`), 213 | KEY `group_name_index` (`name`) 214 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 215 | 216 | -- ---------------------------- 217 | 218 | -- Records of security_group 219 | 220 | -- ---------------------------- 221 | 222 | -------------------------------------------------------------------------------- /src/main/resources/mybatis/config.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/main/resources/mybatis/mapper/ClientSecretMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | client_id, client_secret, tenant_id, status, purpose, update_time, create_time, create_by, update_by 18 | 19 | 20 | 21 | INSERT INTO oauth_client_details (client_id, client_secret, tenant_id, 22 | status, purpose, create_time 23 | ) 24 | VALUES (#{clientId,jdbcType=VARCHAR}, #{clientSecret,jdbcType=VARCHAR}, 25 | #{tenantId,javaType=UUID,jdbcType=OTHER,typeHandler=UUIDTypeHandler}, 26 | #{status,jdbcType=VARCHAR}, #{purpose, jdbcType=VARCHAR}, current_timestamp 27 | ) 28 | 29 | 30 | 50 | 51 | 65 | 66 | 67 | UPDATE oauth_client_details 68 | 69 | 70 | status = #{status, jdbcType=VARCHAR}, 71 | 72 | 73 | client_secret = #{clientSecret, jdbcType=VARCHAR}, 74 | 75 | 76 | purpose = #{purpose, jdbcType=VARCHAR}, 77 | 78 | update_time = current_timestamp 79 | 80 | 81 | client_id = #{clientId, jdbcType=VARCHAR} 82 | 83 | 84 | 85 | 86 | UPDATE oauth_client_details 87 | SET 88 | status = #{status, jdbcType=VARCHAR} 89 | 90 | 91 | tenant_id = #{tenantId, typeHandler=UUIDTypeHandler} 92 | 93 | 94 | client_id = #{clientId, jdbcType=VARCHAR} 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /src/main/resources/mybatis/mapper/PermissionMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | id, permission, description 11 | 12 | 13 | 19 | 20 | 25 | 26 | 27 | DELETE FROM permission 28 | WHERE id = #{id,javaType=UUID,jdbcType=OTHER,typeHandler=UUIDTypeHandler} 29 | 30 | 31 | 32 | insert into permission 33 | 34 | 35 | id, 36 | 37 | 38 | permission, 39 | 40 | 41 | description, 42 | 43 | 44 | 45 | 46 | #{id,javaType=UUID,jdbcType=OTHER,typeHandler=UUIDTypeHandler}, 47 | 48 | 49 | #{permission,jdbcType=VARCHAR}, 50 | 51 | 52 | #{description,jdbcType=VARCHAR}, 53 | 54 | 55 | 56 | 57 | update permission 58 | 59 | 60 | permission = #{permission,jdbcType=VARCHAR}, 61 | 62 | 63 | where id = #{id,javaType=UUID,jdbcType=OTHER,typeHandler=UUIDTypeHandler} 64 | 65 | 66 | 67 | UPDATE permission 68 | SET permission = #{permission,jdbcType=VARCHAR} 69 | WHERE id = #{id,javaType=UUID,jdbcType=OTHER,typeHandler=UUIDTypeHandler} 70 | 71 | 72 | 73 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /src/main/resources/mybatis/mapper/RoleMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | id, name, update_time, description 12 | 13 | 19 | 20 | 25 | 26 | 27 | delete from role 28 | where id = #{id,javaType=UUID,jdbcType=OTHER,typeHandler=UUIDTypeHandler} 29 | 30 | 31 | 32 | insert into role 33 | 34 | 35 | id, 36 | 37 | 38 | name, 39 | 40 | 41 | update_time, 42 | 43 | 44 | description, 45 | 46 | 47 | 48 | 49 | #{id,javaType=UUID,jdbcType=OTHER,typeHandler=UUIDTypeHandler}, 50 | 51 | 52 | #{name,jdbcType=VARCHAR}, 53 | 54 | 55 | #{updateTime,jdbcType=TIMESTAMP}, 56 | 57 | 58 | #{description,jdbcType=VARCHAR}, 59 | 60 | 61 | 62 | 63 | 64 | update role 65 | 66 | 67 | name = #{name,jdbcType=VARCHAR}, 68 | 69 | 70 | update_time = #{updateTime,jdbcType=TIMESTAMP}, 71 | 72 | 73 | description = #{description,jdbcType=VARCHAR}, 74 | 75 | 76 | where id = #{id,javaType=UUID,jdbcType=OTHER,typeHandler=UUIDTypeHandler} 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /src/main/resources/mybatis/mapper/RolePermissionMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | id, role_id, permission_id 12 | 13 | 14 | 20 | 21 | 22 | delete from role_permission 23 | where id = #{id,jdbcType=BIGINT} 24 | 25 | 26 | 27 | 28 | delete from role_permission 29 | where role_id = #{roleId,javaType=UUID,jdbcType=OTHER,typeHandler=UUIDTypeHandler} 30 | and permission_id = #{permissionId,javaType=UUID,jdbcType=OTHER,typeHandler=UUIDTypeHandler} 31 | 32 | 33 | 34 | 35 | insert into role_permission 36 | 37 | 38 | id, 39 | 40 | 41 | role_id, 42 | 43 | 44 | permission_id, 45 | 46 | 47 | 48 | 49 | #{id,jdbcType=BIGINT}, 50 | 51 | 52 | #{roleId,javaType=UUID,jdbcType=OTHER,typeHandler=UUIDTypeHandler}, 53 | 54 | 55 | #{permissionId,javaType=UUID,jdbcType=OTHER,typeHandler=UUIDTypeHandler}, 56 | 57 | 58 | 59 | 60 | update role_permission 61 | 62 | 63 | role_id = #{roleId,javaType=UUID,jdbcType=OTHER,typeHandler=UUIDTypeHandler}, 64 | 65 | 66 | permission_id = #{permissionId,javaType=UUID,jdbcType=OTHER,typeHandler=UUIDTypeHandler}, 67 | 68 | 69 | where id = #{id,jdbcType=BIGINT} 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /src/main/resources/mybatis/mapper/UserAccessMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | id, user_id, access_level 11 | 12 | 13 | 14 | delete from user_access 15 | where user_id = #{userId,javaType=UUID,jdbcType=OTHER,typeHandler=UUIDTypeHandler} 16 | 17 | 18 | 23 | 28 | 29 | 30 | insert into user_access /*SECURITY_IU_DAS|USER:TENANT:tenantId|SECURITY_IU_DAE*/(user_id, 31 | tenant_id, access_level 32 | ) 33 | values (#{userId,jdbcType=OTHER,typeHandler=UUIDTypeHandler}, 34 | #{tenantId,jdbcType=OTHER,typeHandler=UUIDTypeHandler}, #{accessLevel,jdbcType=INTEGER} 35 | ) 36 | 37 | 38 | update user_access/*SECURITY_IU_DAS|USER:TENANT:tenantId|SECURITY_IU_DAE*/ 39 | 40 | 41 | user_id = #{userId,jdbcType=OTHER,typeHandler=UUIDTypeHandler}, 42 | 43 | 44 | tenant_id = #{tenantId,jdbcType=OTHER,typeHandler=UUIDTypeHandler}, 45 | 46 | 47 | access_level = #{accessLevel,jdbcType=INTEGER}, 48 | 49 | 50 | where id = #{id,jdbcType=BIGINT} and tenant_id = 51 | #{oldTenantId,jdbcType=OTHER,typeHandler=UUIDTypeHandler}/*SECURITY_DAS|USER:TENANT:and tenant_id|SECURITY_DAE*/ 52 | 53 | 54 | update user_access/*SECURITY_IU_DAS|USER:TENANT:tenantId|SECURITY_IU_DAE*/ 55 | 56 | 57 | user_id = #{userId,jdbcType=OTHER,typeHandler=UUIDTypeHandler}, 58 | 59 | 60 | tenant_id = #{tenantId,jdbcType=OTHER,typeHandler=UUIDTypeHandler}, 61 | 62 | 63 | access_level = #{accessLevel,jdbcType=INTEGER}, 64 | 65 | 66 | where id = #{id,jdbcType=BIGINT} 67 | 68 | 69 | -------------------------------------------------------------------------------- /src/main/resources/mybatis/mapper/UserRoleMapper.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | id, user_id, role_id, is_default 13 | 14 | 15 | 21 | 22 | 23 | 29 | 30 | 31 | 32 | delete from user_role 33 | where id = #{id,jdbcType=BIGINT} 34 | 35 | 36 | 37 | delete from user_role 38 | where user_id = #{userId,javaType=UUID,jdbcType=OTHER,typeHandler=UUIDTypeHandler} 39 | 40 | 41 | 42 | insert into user_role 43 | 44 | 45 | user_id, 46 | 47 | 48 | role_id, 49 | 50 | 51 | is_default, 52 | 53 | 54 | 55 | 56 | #{userId,javaType=UUID,jdbcType=OTHER,typeHandler=UUIDTypeHandler}, 57 | 58 | 59 | #{roleId,javaType=UUID,jdbcType=OTHER,typeHandler=UUIDTypeHandler}, 60 | 61 | 62 | #{isDefault,jdbcType=BIT}, 63 | 64 | 65 | 66 | 67 | update user_role 68 | 69 | 70 | user_id = #{userId,javaType=UUID,jdbcType=OTHER,typeHandler=UUIDTypeHandler}, 71 | 72 | 73 | role_id = #{roleId,javaType=UUID,jdbcType=OTHER,typeHandler=UUIDTypeHandler}, 74 | 75 | 76 | is_default = #{isDefault,jdbcType=BIT}, 77 | 78 | 79 | where id = #{id,jdbcType=BIGINT} 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /src/test/java/com/blueskykong/auth/AuthApplicationTest.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth; 2 | 3 | 4 | import com.blueskykong.auth.config.BaseServiceTest; 5 | import com.blueskykong.auth.dao.ClientSecretDAO; 6 | import com.blueskykong.auth.dto.ApiClientDTO; 7 | import com.blueskykong.auth.entity.ClientSecret; 8 | import com.blueskykong.auth.service.ClientSecretService; 9 | import org.junit.Assert; 10 | import org.junit.Before; 11 | import org.junit.Test; 12 | import org.junit.runner.RunWith; 13 | import org.mockito.Mock; 14 | import org.springframework.boot.test.context.SpringBootTest; 15 | import org.springframework.test.annotation.DirtiesContext; 16 | import org.springframework.test.context.ContextConfiguration; 17 | import org.springframework.test.context.junit4.SpringRunner; 18 | 19 | import java.util.UUID; 20 | 21 | import static org.mockito.Mockito.when; 22 | 23 | /** 24 | * @author keets 25 | * @date 2016/12/5 26 | */ 27 | 28 | @RunWith(SpringRunner.class) 29 | @SpringBootTest("classpath:application-test.yml") 30 | @DirtiesContext 31 | //@ContextConfiguration(locations = {"classpath:application-test.yml"}) 32 | public class AuthApplicationTest extends BaseServiceTest { 33 | 34 | @Mock 35 | private ClientSecretDAO clientSecretDao; 36 | 37 | @Mock 38 | private ClientSecretService clientSecretService; 39 | 40 | @Before 41 | public void setUp() { 42 | ApiClientDTO mockClient = new ApiClientDTO(); 43 | mockClient.setClientId("test"); 44 | mockClient.setClientSecret("test"); 45 | mockClient.setPurpose("test.."); 46 | ClientSecret clientSecret = new ClientSecret.ClientSecretBuilder() 47 | .withTenantId(UUID.randomUUID()) 48 | .build(); 49 | when(clientSecretService.getClientSecretByClientId("test")).thenReturn(mockClient); 50 | 51 | // when(clientSecretDao.get(clientSecret)).thenReturn() 52 | } 53 | 54 | @Test 55 | public void getClientSecretByClientIdTest() { 56 | ApiClientDTO apiClientDTO = clientSecretService.getClientSecretByClientId("test"); 57 | Assert.assertEquals(apiClientDTO.getClientSecret(), "test"); 58 | } 59 | 60 | 61 | } -------------------------------------------------------------------------------- /src/test/java/com/blueskykong/auth/config/BaseServiceTest.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.config; 2 | 3 | import org.junit.runner.RunWith; 4 | import org.mockito.MockitoAnnotations; 5 | import org.springframework.beans.factory.DisposableBean; 6 | import org.springframework.beans.factory.InitializingBean; 7 | import org.springframework.security.core.context.SecurityContextHolder; 8 | import org.springframework.test.context.ContextConfiguration; 9 | import org.springframework.test.context.junit4.SpringRunner; 10 | 11 | @RunWith(SpringRunner.class) 12 | @ContextConfiguration(initializers = {CustomContextInitializer.class}, classes = {TestJdbcConfig 13 | .class}) 14 | public abstract class BaseServiceTest implements InitializingBean, DisposableBean { 15 | 16 | public BaseServiceTest() { 17 | MockitoAnnotations.initMocks(this); 18 | } 19 | 20 | @Override 21 | public void afterPropertiesSet() throws Exception { 22 | this.destroy(); 23 | } 24 | 25 | @Override 26 | public void destroy() throws Exception { 27 | SecurityContextHolder.clearContext(); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/com/blueskykong/auth/config/CustomContextInitializer.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.config; 2 | 3 | import org.springframework.boot.env.YamlPropertySourceLoader; 4 | import org.springframework.context.ApplicationContextInitializer; 5 | import org.springframework.context.ConfigurableApplicationContext; 6 | import org.springframework.core.env.PropertySource; 7 | import org.springframework.core.io.Resource; 8 | 9 | import java.io.IOException; 10 | import java.util.List; 11 | 12 | public class CustomContextInitializer implements ApplicationContextInitializer { 13 | 14 | @Override 15 | public void initialize(ConfigurableApplicationContext applicationContext) { 16 | try { 17 | Resource resource = applicationContext.getResource("classpath:application-test.yml"); 18 | YamlPropertySourceLoader sourceLoader = new YamlPropertySourceLoader(); 19 | List> yamlTestProperties = sourceLoader.load("test-properties", resource); 20 | applicationContext.getEnvironment().getPropertySources().addFirst(yamlTestProperties.get(0)); 21 | } catch (Exception e) { 22 | throw new RuntimeException(e); 23 | } 24 | } 25 | 26 | } 27 | 28 | -------------------------------------------------------------------------------- /src/test/java/com/blueskykong/auth/config/TestJdbcConfig.java: -------------------------------------------------------------------------------- 1 | package com.blueskykong.auth.config; 2 | 3 | import org.springframework.boot.context.properties.ConfigurationProperties; 4 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 5 | import org.springframework.boot.jdbc.DataSourceBuilder; 6 | import org.springframework.context.annotation.AdviceMode; 7 | import org.springframework.context.annotation.Bean; 8 | import org.springframework.context.annotation.Configuration; 9 | import org.springframework.jdbc.datasource.DataSourceTransactionManager; 10 | import org.springframework.test.context.ContextConfiguration; 11 | import org.springframework.transaction.annotation.EnableTransactionManagement; 12 | 13 | import javax.sql.DataSource; 14 | 15 | /** 16 | * @author keets 17 | * @data 2018/9/3.` 18 | */ 19 | @Configuration 20 | @EnableTransactionManagement(mode = AdviceMode.ASPECTJ) 21 | @EnableConfigurationProperties 22 | @ContextConfiguration(initializers = {CustomContextInitializer.class}) 23 | public class TestJdbcConfig { 24 | 25 | @Bean 26 | @ConfigurationProperties(prefix = "spring.datasource") 27 | public DataSource dataSource() { 28 | return DataSourceBuilder.create().build(); 29 | } 30 | 31 | @Bean 32 | public DataSourceTransactionManager transactionManager() { 33 | return new DataSourceTransactionManager(dataSource()); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/test/resources/application-test.yml: -------------------------------------------------------------------------------- 1 | 2 | 3 | ribbon: 4 | ReadTimeout: 10000 5 | 6 | hystrix: 7 | command: 8 | default: 9 | execution: 10 | isolation: 11 | strategy: THREAD 12 | thread: 13 | timeoutInMilliseconds: 10000 14 | management: 15 | health: 16 | db: 17 | enabled: false 18 | 19 | 20 | --------------------------------------------------------------------------------