├── authz └── src │ ├── main │ ├── webapp │ │ ├── resources │ │ │ └── readme.txt │ │ ├── favicon.ico │ │ ├── loading.jsp │ │ └── WEB-INF │ │ │ ├── decorators.xml │ │ │ ├── jsp │ │ │ ├── comm-header.jsp │ │ │ ├── unauthorized.jsp │ │ │ ├── decorators │ │ │ │ └── main.jsp │ │ │ ├── index.jsp │ │ │ ├── login.jsp │ │ │ └── oauth │ │ │ │ ├── oauth_approval.jsp │ │ │ │ └── oauth_login.jsp │ │ │ ├── log4j.xml │ │ │ └── mkk-servlet.xml │ ├── java │ │ └── com │ │ │ └── monkeyk │ │ │ └── os │ │ │ ├── service │ │ │ ├── impl │ │ │ │ └── Readme.txt │ │ │ ├── dto │ │ │ │ └── LoginDto.java │ │ │ ├── business │ │ │ │ ├── AbstractOAuthHolder.java │ │ │ │ ├── AbstractAccessTokenHandler.java │ │ │ │ ├── AccessTokenRetriever.java │ │ │ │ ├── AuthCodeRetriever.java │ │ │ │ ├── AuthorizationCodeAccessTokenRetriever.java │ │ │ │ ├── NewAccessTokenRetriever.java │ │ │ │ ├── AccessTokenByRefreshTokenChanger.java │ │ │ │ ├── ClientCredentialsAccessTokenRetriever.java │ │ │ │ └── PasswordAccessTokenRetriever.java │ │ │ └── OauthService.java │ │ │ ├── domain │ │ │ └── oauth │ │ │ │ ├── AuthenticationIdGenerator.java │ │ │ │ ├── OauthRepository.java │ │ │ │ ├── OauthCacheRepository.java │ │ │ │ └── DefaultAuthenticationIdGenerator.java │ │ │ ├── web │ │ │ ├── context │ │ │ │ ├── BeanContextLoaderListener.java │ │ │ │ ├── MkkCharacterEncodingFilter.java │ │ │ │ └── OAuthShiroHandlerExceptionResolver.java │ │ │ ├── controller │ │ │ │ ├── OauthTokenController.java │ │ │ │ └── ShiroController.java │ │ │ └── WebUtils.java │ │ │ ├── infrastructure │ │ │ ├── shiro │ │ │ │ └── AuthzRedisRealm.java │ │ │ ├── jdbc │ │ │ │ └── UsersJdbcRepository.java │ │ │ └── UsersRedisRepository.java │ │ │ └── oauth │ │ │ ├── OAuthAuthxRequest.java │ │ │ ├── token │ │ │ ├── OAuthTokenHandler.java │ │ │ ├── OAuthTokenHandleDispatcher.java │ │ │ ├── RefreshTokenHandler.java │ │ │ ├── ClientCredentialsTokenHandler.java │ │ │ ├── PasswordTokenHandler.java │ │ │ ├── AbstractOAuthTokenHandler.java │ │ │ └── AuthorizationCodeTokenHandler.java │ │ │ ├── OAuthTokenxRequest.java │ │ │ ├── authorize │ │ │ └── CodeAuthorizeHandler.java │ │ │ ├── validator │ │ │ ├── TokenClientDetailsValidator.java │ │ │ ├── ClientCredentialsClientDetailsValidator.java │ │ │ ├── CodeClientDetailsValidator.java │ │ │ ├── PasswordClientDetailsValidator.java │ │ │ └── AbstractOauthTokenValidator.java │ │ │ └── OAuthHandler.java │ └── resources │ │ ├── authz.properties │ │ ├── logging.properties │ │ └── spring │ │ ├── authz-redis.xml │ │ └── authz-security.xml │ └── test │ ├── resources │ ├── test.properties │ └── log4j.properties │ └── java │ └── com │ └── monkeyk │ └── os │ ├── web │ ├── WebUtilsTest.java │ └── ShiroTest.java │ ├── ContextTest.java │ ├── TestApplicationContextInitializer.java │ ├── domain │ └── oauth │ │ ├── AuthenticationIdGeneratorTest.java │ │ └── AccessTokenTest.java │ └── infrastructure │ └── jdbc │ └── UsersJdbcRepositoryTest.java ├── core └── src │ ├── main │ ├── resources │ │ └── README.txt │ └── java │ │ └── com │ │ └── monkeyk │ │ └── os │ │ ├── oauth │ │ └── shiro │ │ │ ├── README.txt │ │ │ ├── OAuth2SubjectFactory.java │ │ │ └── OAuth2Token.java │ │ ├── domain │ │ ├── shared │ │ │ ├── Repository.java │ │ │ ├── GuidGenerator.java │ │ │ └── BeanProvider.java │ │ ├── oauth │ │ │ ├── Constants.java │ │ │ └── OauthCode.java │ │ ├── users │ │ │ ├── UsersRepository.java │ │ │ ├── Roles.java │ │ │ ├── UserRoles.java │ │ │ ├── RolesPermissions.java │ │ │ └── Users.java │ │ ├── AbstractDomain.java │ │ └── AbstractIdDomain.java │ │ └── infrastructure │ │ ├── ThreadLocalHolder.java │ │ ├── jdbc │ │ ├── AbstractJdbcRepository.java │ │ ├── OauthCodeRowMapper.java │ │ ├── UserRolesRowMapper.java │ │ ├── AccessTokenRowMapper.java │ │ ├── RolesPermissionsRowMapper.java │ │ ├── RolesRowMapper.java │ │ ├── UsersRowMapper.java │ │ └── ClientDetailsRowMapper.java │ │ ├── shiro │ │ └── MkkJdbcRealm.java │ │ └── cache │ │ ├── CacheNames.java │ │ └── AbstractCacheSupport.java │ └── test │ ├── resources │ ├── test.properties │ └── log4j.properties │ └── java │ └── com │ └── monkeyk │ └── os │ └── TestApplicationContextInitializer.java ├── .gitignore ├── resources └── src │ ├── main │ ├── java │ │ └── com │ │ │ └── monkeyk │ │ │ └── os │ │ │ ├── oauth │ │ │ ├── shiro │ │ │ │ ├── README.txt │ │ │ │ └── OAuth2AuthenticationException.java │ │ │ └── resources │ │ │ │ ├── MkkOAuthPrincipal.java │ │ │ │ ├── MkkOAuthDecision.java │ │ │ │ └── MkkOAuthRSProvider.java │ │ │ ├── service │ │ │ ├── impl │ │ │ │ ├── Readme.txt │ │ │ │ └── OAuthRSServiceImpl.java │ │ │ ├── dto │ │ │ │ ├── SystemTimeDto.java │ │ │ │ └── UsernameDto.java │ │ │ └── OAuthRSService.java │ │ │ ├── domain │ │ │ └── rs │ │ │ │ ├── OAuthRSRepository.java │ │ │ │ ├── RSOAuthClient.java │ │ │ │ └── OAuthRSCacheRepository.java │ │ │ ├── web │ │ │ ├── context │ │ │ │ ├── BeanContextLoaderListener.java │ │ │ │ ├── MkkCharacterEncodingFilter.java │ │ │ │ └── OAuthShiroHandlerExceptionResolver.java │ │ │ ├── controller │ │ │ │ ├── OauthResourcesController.java │ │ │ │ └── MobileResourcesController.java │ │ │ └── WebUtils.java │ │ │ └── infrastructure │ │ │ ├── jdbc │ │ │ ├── OAuthRSJdbcRepository.java │ │ │ └── UsersRSJdbcRepository.java │ │ │ └── UsersRSRedisRepository.java │ ├── webapp │ │ ├── favicon.ico │ │ ├── WEB-INF │ │ │ ├── log4j.xml │ │ │ └── mkk-servlet.xml │ │ └── loading.jsp │ └── resources │ │ ├── resources.properties │ │ ├── logging.properties │ │ └── spring │ │ └── rs-redis.xml │ └── test │ ├── resources │ ├── test.properties │ └── log4j.properties │ └── java │ └── com │ └── monkeyk │ └── os │ ├── web │ ├── WebUtilsTest.java │ └── ShiroTest.java │ ├── ContextTest.java │ ├── TestApplicationContextInitializer.java │ ├── infrastructure │ ├── jdbc │ │ └── OAuthRSJdbcRepositoryTest.java │ └── UsersRSRedisRepositoryTest.java │ └── domain │ └── oauth │ └── AccessTokenTest.java ├── index.html ├── pom.xml ├── others ├── database │ └── initial-db.ddl └── oauth_test.txt └── README.md /authz/src/main/webapp/resources/readme.txt: -------------------------------------------------------------------------------- 1 | All static resources in here. -------------------------------------------------------------------------------- /core/src/main/resources/README.txt: -------------------------------------------------------------------------------- 1 | If have ext. properties 2 | Add here. -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Package Files # 4 | *.jar 5 | *.war 6 | *.ear 7 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/service/impl/Readme.txt: -------------------------------------------------------------------------------- 1 | 2 | Add AOP transaction in the package. -------------------------------------------------------------------------------- /core/src/main/java/com/monkeyk/os/oauth/shiro/README.txt: -------------------------------------------------------------------------------- 1 | 2 | Override Shiro for support OAuth 3 | -------------------------------------------------------------------------------- /resources/src/main/java/com/monkeyk/os/oauth/shiro/README.txt: -------------------------------------------------------------------------------- 1 | 2 | Override Shiro for support OAuth 3 | -------------------------------------------------------------------------------- /resources/src/main/java/com/monkeyk/os/service/impl/Readme.txt: -------------------------------------------------------------------------------- 1 | 2 | Add AOP transaction in the package. -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 |

Go to OSR...

2 | 3 | -------------------------------------------------------------------------------- /authz/src/main/webapp/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeyk/oauth2-shiro-redis/HEAD/authz/src/main/webapp/favicon.ico -------------------------------------------------------------------------------- /resources/src/main/webapp/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeyk/oauth2-shiro-redis/HEAD/resources/src/main/webapp/favicon.ico -------------------------------------------------------------------------------- /authz/src/main/resources/authz.properties: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/monkeyk/oauth2-shiro-redis/HEAD/authz/src/main/resources/authz.properties -------------------------------------------------------------------------------- /core/src/main/java/com/monkeyk/os/domain/shared/Repository.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.domain.shared; 2 | 3 | /** 4 | * @author Shengzhao Li 5 | */ 6 | 7 | public interface Repository { 8 | 9 | 10 | } -------------------------------------------------------------------------------- /authz/src/main/webapp/loading.jsp: -------------------------------------------------------------------------------- 1 | <%-- 2 | * 3 | * @author Shengzhao Li 4 | --%> 5 | 6 | <%@ page contentType="text/html;charset=UTF-8" language="java" %> 7 | <% 8 | request.getRequestDispatcher("index").forward(request, response); 9 | %> -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/domain/oauth/AuthenticationIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.domain.oauth; 2 | 3 | /** 4 | * 15-6-20 5 | * 6 | * @author Shengzhao Li 7 | */ 8 | 9 | public interface AuthenticationIdGenerator { 10 | 11 | public String generate(String clientId, String username, String scope); 12 | 13 | } -------------------------------------------------------------------------------- /core/src/main/java/com/monkeyk/os/domain/shared/GuidGenerator.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.domain.shared; 2 | 3 | import java.util.UUID; 4 | 5 | /** 6 | * @author Shengzhao Li 7 | */ 8 | public abstract class GuidGenerator { 9 | 10 | public static String generate() { 11 | return UUID.randomUUID().toString().replaceAll("-", ""); 12 | } 13 | } -------------------------------------------------------------------------------- /core/src/test/resources/test.properties: -------------------------------------------------------------------------------- 1 | #JDBC configuration information 2 | jdbc.driverClassName=com.mysql.jdbc.Driver 3 | ############ 4 | # localhost 5 | ############ 6 | jdbc.url=jdbc:mysql://localhost:3306/oauth2_shiro_test?autoReconnect=true&autoReconnectForPools=true&useUnicode=true&characterEncoding=utf8 7 | jdbc.username=andaily 8 | jdbc.password=andaily 9 | 10 | 11 | -------------------------------------------------------------------------------- /authz/src/main/webapp/WEB-INF/decorators.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | /* 8 | 9 | 10 | 11 | 12 | /resources/** 13 | 14 | 15 | -------------------------------------------------------------------------------- /authz/src/main/webapp/WEB-INF/jsp/comm-header.jsp: -------------------------------------------------------------------------------- 1 | <%--<%@ page session="false" %>--%> 2 | 3 | <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 4 | <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> 5 | <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> 6 | <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %> 7 | <%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %> -------------------------------------------------------------------------------- /core/src/main/java/com/monkeyk/os/infrastructure/ThreadLocalHolder.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.infrastructure; 2 | 3 | /** 4 | * @author Shengzhao Li 5 | */ 6 | public abstract class ThreadLocalHolder { 7 | 8 | private static ThreadLocal clientIpThreadLocal = new ThreadLocal<>(); 9 | 10 | public static void clientIp(String clientIp) { 11 | clientIpThreadLocal.set(clientIp); 12 | } 13 | 14 | public static String clientIp() { 15 | return clientIpThreadLocal.get(); 16 | } 17 | } -------------------------------------------------------------------------------- /core/src/main/java/com/monkeyk/os/infrastructure/jdbc/AbstractJdbcRepository.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.infrastructure.jdbc; 2 | 3 | import com.monkeyk.os.domain.shared.Repository; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.jdbc.core.JdbcTemplate; 6 | 7 | /** 8 | * 15-6-13 9 | * 10 | * @author Shengzhao Li 11 | */ 12 | public abstract class AbstractJdbcRepository implements Repository { 13 | 14 | 15 | @Autowired 16 | protected JdbcTemplate jdbcTemplate; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /resources/src/main/resources/resources.properties: -------------------------------------------------------------------------------- 1 | #JDBC configuration information 2 | jdbc.driverClassName=com.mysql.jdbc.Driver 3 | ############ 4 | # MySQL DB 5 | ############ 6 | jdbc.url=jdbc:mysql://localhost:3306/oauth2_shiro_redis?autoReconnect=true&autoReconnectForPools=true&useUnicode=true&characterEncoding=utf8 7 | jdbc.username=andaily 8 | jdbc.password=andaily 9 | 10 | 11 | #Redis configuration 12 | redis.host=127.0.0.1 13 | redis.port=6379 14 | redis.password= 15 | redis.database=1 16 | redis.timeout=2000 17 | redis.usepool=true 18 | -------------------------------------------------------------------------------- /authz/src/test/resources/test.properties: -------------------------------------------------------------------------------- 1 | #JDBC configuration information 2 | jdbc.driverClassName=com.mysql.jdbc.Driver 3 | ############ 4 | # localhost 5 | ############ 6 | jdbc.url=jdbc:mysql://localhost:3306/oauth2_shiro_redis_test?autoReconnect=true&autoReconnectForPools=true&useUnicode=true&characterEncoding=utf8 7 | jdbc.username=andaily 8 | jdbc.password=andaily 9 | 10 | 11 | #Redis configuration 12 | redis.host=127.0.0.1 13 | redis.port=6379 14 | redis.password= 15 | redis.database=1 16 | redis.timeout=2000 17 | redis.usepool=true 18 | 19 | 20 | -------------------------------------------------------------------------------- /resources/src/test/resources/test.properties: -------------------------------------------------------------------------------- 1 | #JDBC configuration information 2 | jdbc.driverClassName=com.mysql.jdbc.Driver 3 | ############ 4 | # localhost 5 | ############ 6 | jdbc.url=jdbc:mysql://localhost:3306/oauth2_shiro_redis_test?autoReconnect=true&autoReconnectForPools=true&useUnicode=true&characterEncoding=utf8 7 | jdbc.username=andaily 8 | jdbc.password=andaily 9 | 10 | 11 | #Redis configuration 12 | redis.host=127.0.0.1 13 | redis.port=6379 14 | redis.password= 15 | redis.database=1 16 | redis.timeout=2000 17 | redis.usepool=true 18 | 19 | 20 | -------------------------------------------------------------------------------- /resources/src/main/java/com/monkeyk/os/domain/rs/OAuthRSRepository.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.domain.rs; 2 | 3 | import com.monkeyk.os.domain.oauth.AccessToken; 4 | import com.monkeyk.os.domain.oauth.ClientDetails; 5 | import com.monkeyk.os.domain.shared.Repository; 6 | 7 | /** 8 | * 2015/10/7 9 | * 10 | * @author Shengzhao Li 11 | */ 12 | 13 | public interface OAuthRSRepository extends Repository { 14 | 15 | AccessToken findAccessTokenByTokenId(String tokenId); 16 | 17 | ClientDetails findClientDetailsByClientIdAndResourceIds(String clientId, String resourceIds); 18 | } -------------------------------------------------------------------------------- /resources/src/main/java/com/monkeyk/os/service/dto/SystemTimeDto.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.service.dto; 2 | 3 | import com.monkeyk.os.infrastructure.DateUtils; 4 | 5 | import java.io.Serializable; 6 | 7 | /** 8 | * 2015/9/29 9 | * 10 | * @author Shengzhao Li 11 | */ 12 | public class SystemTimeDto implements Serializable { 13 | 14 | private long time = DateUtils.now().getTime(); 15 | 16 | 17 | public SystemTimeDto() { 18 | } 19 | 20 | public long getTime() { 21 | return time; 22 | } 23 | 24 | public void setTime(long time) { 25 | this.time = time; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /core/src/main/java/com/monkeyk/os/domain/oauth/Constants.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.domain.oauth; 2 | 3 | /** 4 | * 2015/6/25 5 | * 6 | * @author Shengzhao Li 7 | */ 8 | public abstract class Constants { 9 | 10 | 11 | public static final String REQUEST_USERNAME = "username"; 12 | public static final String REQUEST_PASSWORD = "password"; 13 | 14 | public static final String REQUEST_USER_OAUTH_APPROVAL = "user_oauth_approval"; 15 | 16 | public static final String OAUTH_LOGIN_VIEW = "oauth_login"; 17 | public static final String OAUTH_APPROVAL_VIEW = "oauth_approval"; 18 | 19 | private Constants() { 20 | } 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /authz/src/test/java/com/monkeyk/os/web/WebUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.web; 2 | 3 | import org.apache.oltu.oauth2.common.utils.OAuthUtils; 4 | import org.testng.annotations.Test; 5 | 6 | import java.util.Arrays; 7 | 8 | import static org.testng.Assert.assertNotNull; 9 | 10 | public class WebUtilsTest { 11 | 12 | 13 | @Test 14 | public void testDecodeHeader() throws Exception { 15 | 16 | String text = "Basic dXNlcm5hbWU6cGFzc3dvcmQ="; 17 | 18 | final String[] strings = OAuthUtils.decodeClientAuthenticationHeader(text); 19 | assertNotNull(strings); 20 | 21 | System.out.println(Arrays.toString(strings)); 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /authz/src/test/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | #\u914D\u7F6E\u6839Logger , file, db 2 | log4j.rootLogger=INFO, stdout 3 | 4 | #\u914D\u7F6E\u65E5\u5FD7\u4FE1\u606F\u8F93\u51FA\u76EE\u7684\u5730(appender) 5 | #\u63A7\u5236\u53F0\u8F93\u51FA 6 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 7 | #\u63A7\u5236\u53F0\u8F93\u51FA\u7684\u9009\u9879(\u53EF\u9009) 8 | #log4j.appender.stdout.Threshold=INFO 9 | #log4j.appender.stdout.ImmediateFlush=true 10 | log4j.appender.stdout.Target=System.out 11 | #\u63A7\u5236\u53F0\u8F93\u51FA\u7684\u683C\u5F0F 12 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 13 | log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n 14 | -------------------------------------------------------------------------------- /core/src/test/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | #\u914D\u7F6E\u6839Logger , file, db 2 | log4j.rootLogger=INFO, stdout 3 | 4 | #\u914D\u7F6E\u65E5\u5FD7\u4FE1\u606F\u8F93\u51FA\u76EE\u7684\u5730(appender) 5 | #\u63A7\u5236\u53F0\u8F93\u51FA 6 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 7 | #\u63A7\u5236\u53F0\u8F93\u51FA\u7684\u9009\u9879(\u53EF\u9009) 8 | #log4j.appender.stdout.Threshold=INFO 9 | #log4j.appender.stdout.ImmediateFlush=true 10 | log4j.appender.stdout.Target=System.out 11 | #\u63A7\u5236\u53F0\u8F93\u51FA\u7684\u683C\u5F0F 12 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 13 | log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n 14 | -------------------------------------------------------------------------------- /resources/src/test/java/com/monkeyk/os/web/WebUtilsTest.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.web; 2 | 3 | import org.apache.oltu.oauth2.common.utils.OAuthUtils; 4 | import org.testng.annotations.Test; 5 | 6 | import java.util.Arrays; 7 | 8 | import static org.testng.Assert.assertNotNull; 9 | 10 | public class WebUtilsTest { 11 | 12 | 13 | @Test 14 | public void testDecodeHeader() throws Exception { 15 | 16 | String text = "Basic dXNlcm5hbWU6cGFzc3dvcmQ="; 17 | 18 | final String[] strings = OAuthUtils.decodeClientAuthenticationHeader(text); 19 | assertNotNull(strings); 20 | 21 | System.out.println(Arrays.toString(strings)); 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /resources/src/test/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | #\u914D\u7F6E\u6839Logger , file, db 2 | log4j.rootLogger=INFO, stdout 3 | 4 | #\u914D\u7F6E\u65E5\u5FD7\u4FE1\u606F\u8F93\u51FA\u76EE\u7684\u5730(appender) 5 | #\u63A7\u5236\u53F0\u8F93\u51FA 6 | log4j.appender.stdout=org.apache.log4j.ConsoleAppender 7 | #\u63A7\u5236\u53F0\u8F93\u51FA\u7684\u9009\u9879(\u53EF\u9009) 8 | #log4j.appender.stdout.Threshold=INFO 9 | #log4j.appender.stdout.ImmediateFlush=true 10 | log4j.appender.stdout.Target=System.out 11 | #\u63A7\u5236\u53F0\u8F93\u51FA\u7684\u683C\u5F0F 12 | log4j.appender.stdout.layout=org.apache.log4j.PatternLayout 13 | log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n 14 | -------------------------------------------------------------------------------- /authz/src/main/resources/logging.properties: -------------------------------------------------------------------------------- 1 | handlers = org.apache.juli.FileHandler, java.util.logging.ConsoleHandler 2 | 3 | ############################################################ 4 | # Handler specific properties. 5 | # Describes specific configuration info for Handlers. 6 | # The configuration for Tomcat server 7 | ############################################################ 8 | 9 | org.apache.juli.FileHandler.level = FINE 10 | org.apache.juli.FileHandler.directory = ${catalina.base}/logs 11 | org.apache.juli.FileHandler.prefix = error-debug. 12 | 13 | java.util.logging.ConsoleHandler.level = FINE 14 | java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter 15 | -------------------------------------------------------------------------------- /resources/src/main/resources/logging.properties: -------------------------------------------------------------------------------- 1 | handlers = org.apache.juli.FileHandler, java.util.logging.ConsoleHandler 2 | 3 | ############################################################ 4 | # Handler specific properties. 5 | # Describes specific configuration info for Handlers. 6 | # The configuration for Tomcat server 7 | ############################################################ 8 | 9 | org.apache.juli.FileHandler.level = FINE 10 | org.apache.juli.FileHandler.directory = ${catalina.base}/logs 11 | org.apache.juli.FileHandler.prefix = error-debug. 12 | 13 | java.util.logging.ConsoleHandler.level = FINE 14 | java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter 15 | -------------------------------------------------------------------------------- /resources/src/main/java/com/monkeyk/os/oauth/shiro/OAuth2AuthenticationException.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.oauth.shiro; 2 | 3 | import org.apache.shiro.authc.AuthenticationException; 4 | 5 | /** 6 | * 2015/9/29 7 | * 8 | * @author Shengzhao Li 9 | */ 10 | public class OAuth2AuthenticationException extends AuthenticationException { 11 | 12 | public OAuth2AuthenticationException() { 13 | } 14 | 15 | public OAuth2AuthenticationException(String message) { 16 | super(message); 17 | } 18 | 19 | public OAuth2AuthenticationException(Throwable cause) { 20 | super(cause); 21 | } 22 | 23 | public OAuth2AuthenticationException(String message, Throwable cause) { 24 | super(message, cause); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /authz/src/test/java/com/monkeyk/os/ContextTest.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os; 2 | 3 | import com.monkeyk.os.domain.shared.BeanProvider; 4 | import org.springframework.test.context.ContextConfiguration; 5 | import org.springframework.test.context.testng.AbstractTransactionalTestNGSpringContextTests; 6 | import org.springframework.test.context.transaction.BeforeTransaction; 7 | 8 | /** 9 | * @author Shengzhao Li 10 | */ 11 | @ContextConfiguration(locations = {"classpath:/spring/*.xml"}, initializers = {TestApplicationContextInitializer.class}) 12 | public abstract class ContextTest extends AbstractTransactionalTestNGSpringContextTests { 13 | 14 | 15 | @BeforeTransaction 16 | public void before() throws Exception { 17 | BeanProvider.initialize(applicationContext); 18 | } 19 | } -------------------------------------------------------------------------------- /resources/src/test/java/com/monkeyk/os/ContextTest.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os; 2 | 3 | import com.monkeyk.os.domain.shared.BeanProvider; 4 | import org.springframework.test.context.ContextConfiguration; 5 | import org.springframework.test.context.testng.AbstractTransactionalTestNGSpringContextTests; 6 | import org.springframework.test.context.transaction.BeforeTransaction; 7 | 8 | /** 9 | * @author Shengzhao Li 10 | */ 11 | @ContextConfiguration(locations = {"classpath:/spring/*.xml"}, initializers = {TestApplicationContextInitializer.class}) 12 | public abstract class ContextTest extends AbstractTransactionalTestNGSpringContextTests { 13 | 14 | 15 | @BeforeTransaction 16 | public void before() throws Exception { 17 | BeanProvider.initialize(applicationContext); 18 | } 19 | } -------------------------------------------------------------------------------- /authz/src/main/webapp/WEB-INF/log4j.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 | -------------------------------------------------------------------------------- /resources/src/main/webapp/WEB-INF/log4j.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 | -------------------------------------------------------------------------------- /resources/src/main/java/com/monkeyk/os/domain/rs/RSOAuthClient.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.domain.rs; 2 | 3 | import com.monkeyk.os.domain.oauth.ClientDetails; 4 | import org.apache.oltu.oauth2.rsfilter.OAuthClient; 5 | 6 | /** 7 | * 2015/10/7 8 | *

9 | * Wrapper ClientDetails 10 | * implement OAuthClient 11 | * 12 | * @author Shengzhao Li 13 | * @see com.monkeyk.os.domain.oauth.ClientDetails 14 | */ 15 | public class RSOAuthClient implements OAuthClient { 16 | 17 | private ClientDetails clientDetails; 18 | 19 | public RSOAuthClient(ClientDetails clientDetails) { 20 | this.clientDetails = clientDetails; 21 | } 22 | 23 | @Override 24 | public String getClientId() { 25 | return clientDetails.clientId(); 26 | } 27 | 28 | public ClientDetails clientDetails() { 29 | return clientDetails; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /resources/src/main/java/com/monkeyk/os/service/dto/UsernameDto.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.service.dto; 2 | 3 | import java.io.Serializable; 4 | 5 | /** 6 | * 2015/9/29 7 | * 8 | * @author Shengzhao Li 9 | */ 10 | public class UsernameDto implements Serializable { 11 | 12 | private String clientId; 13 | 14 | private String username; 15 | 16 | public UsernameDto(String clientId, String username) { 17 | this.clientId = clientId; 18 | this.username = username; 19 | } 20 | 21 | 22 | public String getClientId() { 23 | return clientId; 24 | } 25 | 26 | public void setClientId(String clientId) { 27 | this.clientId = clientId; 28 | } 29 | 30 | public String getUsername() { 31 | return username; 32 | } 33 | 34 | public void setUsername(String username) { 35 | this.username = username; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /resources/src/main/webapp/loading.jsp: -------------------------------------------------------------------------------- 1 | <%-- 2 | * 3 | * @author Shengzhao Li 4 | --%> 5 | 6 | <%@ page contentType="text/html;charset=UTF-8" language="java" %> 7 | <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | RESOURCES | Oauth2-Shiro 19 | 20 | 21 | 22 | 23 |

OAUTH RESOURCES is work!

24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/web/context/BeanContextLoaderListener.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.web.context; 2 | 3 | import com.monkeyk.os.domain.shared.BeanProvider; 4 | import org.springframework.web.context.ContextLoaderListener; 5 | import org.springframework.web.context.WebApplicationContext; 6 | import org.springframework.web.context.support.WebApplicationContextUtils; 7 | 8 | import javax.servlet.ServletContextEvent; 9 | 10 | /** 11 | * @author Shengzhao Li 12 | */ 13 | public class BeanContextLoaderListener extends ContextLoaderListener { 14 | 15 | 16 | @Override 17 | public void contextInitialized(ServletContextEvent event) { 18 | super.contextInitialized(event); 19 | WebApplicationContext applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(event.getServletContext()); 20 | BeanProvider.initialize(applicationContext); 21 | } 22 | } -------------------------------------------------------------------------------- /authz/src/main/webapp/WEB-INF/jsp/unauthorized.jsp: -------------------------------------------------------------------------------- 1 | <%-- 2 | * Copyright (c) 2013 Andaily Information Technology Co. Ltd 3 | * www.andaily.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * Andaily Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with Andaily Information Technology Co. Ltd. 11 | --%> 12 | <%-- 13 | * 14 | * @author Shengzhao Li 15 | --%> 16 | <%@ page contentType="text/html;charset=UTF-8" language="java" %> 17 | 18 | 19 | 20 | UnAuthorized 21 | 22 | 23 |

unauthorized

24 | Home 25 | Back 26 | 27 | -------------------------------------------------------------------------------- /resources/src/main/java/com/monkeyk/os/web/context/BeanContextLoaderListener.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.web.context; 2 | 3 | import com.monkeyk.os.domain.shared.BeanProvider; 4 | import org.springframework.web.context.ContextLoaderListener; 5 | import org.springframework.web.context.WebApplicationContext; 6 | import org.springframework.web.context.support.WebApplicationContextUtils; 7 | 8 | import javax.servlet.ServletContextEvent; 9 | 10 | /** 11 | * @author Shengzhao Li 12 | */ 13 | public class BeanContextLoaderListener extends ContextLoaderListener { 14 | 15 | 16 | @Override 17 | public void contextInitialized(ServletContextEvent event) { 18 | super.contextInitialized(event); 19 | WebApplicationContext applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(event.getServletContext()); 20 | BeanProvider.initialize(applicationContext); 21 | } 22 | } -------------------------------------------------------------------------------- /core/src/main/java/com/monkeyk/os/infrastructure/jdbc/OauthCodeRowMapper.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.infrastructure.jdbc; 2 | 3 | import com.monkeyk.os.domain.oauth.OauthCode; 4 | import org.springframework.jdbc.core.RowMapper; 5 | 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | 9 | /** 10 | * 15-6-13 11 | * 12 | * @author Shengzhao Li 13 | */ 14 | public class OauthCodeRowMapper implements RowMapper { 15 | 16 | 17 | public OauthCodeRowMapper() { 18 | } 19 | 20 | @Override 21 | public OauthCode mapRow(ResultSet rs, int rowNum) throws SQLException { 22 | final OauthCode oauthCode = new OauthCode() 23 | .clientId(rs.getString("client_id")) 24 | .username(rs.getString("username")) 25 | .code(rs.getString("code")); 26 | 27 | oauthCode.createTime(rs.getTimestamp("create_time")); 28 | return oauthCode; 29 | 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /core/src/main/java/com/monkeyk/os/domain/users/UsersRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.domain.users; 13 | 14 | import com.monkeyk.os.domain.shared.Repository; 15 | 16 | import java.util.List; 17 | 18 | /** 19 | * 2015/10/26 20 | * 21 | * @author Shengzhao Li 22 | */ 23 | 24 | public interface UsersRepository extends Repository { 25 | 26 | Users findUsersByUsername(String username); 27 | 28 | List findRolesByUsername(String username); 29 | } -------------------------------------------------------------------------------- /resources/src/main/java/com/monkeyk/os/service/OAuthRSService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Andaily Information Technology Co. Ltd 3 | * www.andaily.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * Andaily Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with Andaily Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.service; 13 | 14 | import com.monkeyk.os.domain.oauth.AccessToken; 15 | import com.monkeyk.os.domain.oauth.ClientDetails; 16 | 17 | /** 18 | * 2015/7/8 19 | * 20 | * @author Shengzhao Li 21 | */ 22 | 23 | public interface OAuthRSService { 24 | 25 | AccessToken loadAccessTokenByTokenId(String tokenId); 26 | 27 | ClientDetails loadClientDetails(String clientId, String resourceIds); 28 | 29 | } -------------------------------------------------------------------------------- /authz/src/test/java/com/monkeyk/os/TestApplicationContextInitializer.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os; 2 | 3 | import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; 4 | import org.springframework.context.ApplicationContextInitializer; 5 | import org.springframework.context.support.AbstractApplicationContext; 6 | import org.springframework.core.io.ClassPathResource; 7 | 8 | /** 9 | * @author Shengzhao Li 10 | */ 11 | public class TestApplicationContextInitializer implements ApplicationContextInitializer { 12 | 13 | @Override 14 | public void initialize(AbstractApplicationContext applicationContext) { 15 | PropertyPlaceholderConfigurer propertyPlaceholderConfigurer = new PropertyPlaceholderConfigurer(); 16 | //load database.properties 17 | propertyPlaceholderConfigurer.setLocation(new ClassPathResource("test.properties")); 18 | 19 | applicationContext.addBeanFactoryPostProcessor(propertyPlaceholderConfigurer); 20 | 21 | 22 | } 23 | } -------------------------------------------------------------------------------- /core/src/test/java/com/monkeyk/os/TestApplicationContextInitializer.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os; 2 | 3 | import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; 4 | import org.springframework.context.ApplicationContextInitializer; 5 | import org.springframework.context.support.AbstractApplicationContext; 6 | import org.springframework.core.io.ClassPathResource; 7 | 8 | /** 9 | * @author Shengzhao Li 10 | */ 11 | public class TestApplicationContextInitializer implements ApplicationContextInitializer { 12 | 13 | @Override 14 | public void initialize(AbstractApplicationContext applicationContext) { 15 | PropertyPlaceholderConfigurer propertyPlaceholderConfigurer = new PropertyPlaceholderConfigurer(); 16 | //load database.properties 17 | propertyPlaceholderConfigurer.setLocation(new ClassPathResource("test.properties")); 18 | 19 | applicationContext.addBeanFactoryPostProcessor(propertyPlaceholderConfigurer); 20 | 21 | 22 | } 23 | } -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/domain/oauth/OauthRepository.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.domain.oauth; 2 | 3 | import com.monkeyk.os.domain.shared.Repository; 4 | 5 | /** 6 | * 15-6-13 7 | * 8 | * @author Shengzhao Li 9 | */ 10 | public interface OauthRepository extends Repository { 11 | 12 | ClientDetails findClientDetails(String clientId); 13 | 14 | int saveClientDetails(ClientDetails clientDetails); 15 | 16 | int saveOauthCode(OauthCode oauthCode); 17 | 18 | OauthCode findOauthCode(String code, String clientId); 19 | 20 | OauthCode findOauthCodeByUsernameClientId(String username, String clientId); 21 | 22 | int deleteOauthCode(OauthCode oauthCode); 23 | 24 | AccessToken findAccessToken(String clientId, String username, String authenticationId); 25 | 26 | int deleteAccessToken(AccessToken accessToken); 27 | 28 | int saveAccessToken(AccessToken accessToken); 29 | 30 | AccessToken findAccessTokenByRefreshToken(String refreshToken, String clientId); 31 | 32 | 33 | } 34 | -------------------------------------------------------------------------------- /resources/src/test/java/com/monkeyk/os/TestApplicationContextInitializer.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os; 2 | 3 | import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer; 4 | import org.springframework.context.ApplicationContextInitializer; 5 | import org.springframework.context.support.AbstractApplicationContext; 6 | import org.springframework.core.io.ClassPathResource; 7 | 8 | /** 9 | * @author Shengzhao Li 10 | */ 11 | public class TestApplicationContextInitializer implements ApplicationContextInitializer { 12 | 13 | @Override 14 | public void initialize(AbstractApplicationContext applicationContext) { 15 | PropertyPlaceholderConfigurer propertyPlaceholderConfigurer = new PropertyPlaceholderConfigurer(); 16 | //load database.properties 17 | propertyPlaceholderConfigurer.setLocation(new ClassPathResource("test.properties")); 18 | 19 | applicationContext.addBeanFactoryPostProcessor(propertyPlaceholderConfigurer); 20 | 21 | 22 | } 23 | } -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/infrastructure/shiro/AuthzRedisRealm.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.infrastructure.shiro; 13 | 14 | import org.slf4j.Logger; 15 | import org.slf4j.LoggerFactory; 16 | 17 | /** 18 | * 2015/10/27 19 | * 20 | * @author Shengzhao Li 21 | */ 22 | public class AuthzRedisRealm extends RedisRealm { 23 | 24 | 25 | private static final Logger LOG = LoggerFactory.getLogger(AuthzRedisRealm.class); 26 | 27 | 28 | public AuthzRedisRealm() { 29 | super(); 30 | LOG.debug("Initial Authz Realm: {}", this); 31 | } 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /resources/src/main/java/com/monkeyk/os/oauth/resources/MkkOAuthPrincipal.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.oauth.resources; 13 | 14 | import java.security.Principal; 15 | 16 | /** 17 | * 2015/9/25 18 | * 19 | * @author Shengzhao Li 20 | */ 21 | public class MkkOAuthPrincipal implements Principal { 22 | 23 | 24 | private String name; 25 | 26 | public MkkOAuthPrincipal() { 27 | } 28 | 29 | public MkkOAuthPrincipal(String name) { 30 | this.name = name; 31 | } 32 | 33 | @Override 34 | public String getName() { 35 | return name; 36 | } 37 | 38 | 39 | } 40 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/oauth/OAuthAuthxRequest.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.oauth; 2 | 3 | import org.apache.oltu.oauth2.as.request.OAuthAuthzRequest; 4 | import org.apache.oltu.oauth2.common.exception.OAuthProblemException; 5 | import org.apache.oltu.oauth2.common.exception.OAuthSystemException; 6 | import org.apache.oltu.oauth2.common.message.types.ResponseType; 7 | 8 | import javax.servlet.http.HttpServletRequest; 9 | 10 | /** 11 | * 15-6-17 12 | * 13 | * @author Shengzhao Li 14 | */ 15 | public class OAuthAuthxRequest extends OAuthAuthzRequest { 16 | 17 | 18 | public OAuthAuthxRequest(HttpServletRequest request) throws OAuthSystemException, OAuthProblemException { 19 | super(request); 20 | } 21 | 22 | 23 | public boolean isCode() { 24 | return ResponseType.CODE.name().equalsIgnoreCase(this.getResponseType()); 25 | } 26 | 27 | public boolean isToken() { 28 | return ResponseType.TOKEN.name().equalsIgnoreCase(this.getResponseType()); 29 | } 30 | 31 | public HttpServletRequest request() { 32 | return this.request; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /core/src/main/java/com/monkeyk/os/domain/shared/BeanProvider.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.domain.shared; 2 | 3 | import org.springframework.context.ApplicationContext; 4 | 5 | /** 6 | * @author Shengzhao Li 7 | */ 8 | public abstract class BeanProvider { 9 | 10 | private static ApplicationContext applicationContext; 11 | 12 | 13 | public static void initialize(ApplicationContext applicationContext) { 14 | BeanProvider.applicationContext = applicationContext; 15 | } 16 | 17 | /** 18 | * Get Bean by clazz. 19 | * 20 | * @param clazz Class 21 | * @param class type 22 | * @return Bean instance 23 | */ 24 | public static T getBean(Class clazz) { 25 | if (applicationContext == null) { 26 | return null; 27 | } 28 | return applicationContext.getBean(clazz); 29 | } 30 | 31 | @SuppressWarnings("unchecked") 32 | public static T getBean(String beanId) { 33 | if (applicationContext == null) { 34 | return null; 35 | } 36 | return (T) applicationContext.getBean(beanId); 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /core/src/main/java/com/monkeyk/os/domain/oauth/OauthCode.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.domain.oauth; 2 | 3 | import com.monkeyk.os.domain.AbstractDomain; 4 | 5 | /** 6 | * 15-6-17 7 | * 8 | * @author Shengzhao Li 9 | */ 10 | public class OauthCode extends AbstractDomain { 11 | 12 | private static final long serialVersionUID = 7861853986708936572L; 13 | private String code; 14 | 15 | private String username; 16 | 17 | private String clientId; 18 | 19 | public OauthCode() { 20 | } 21 | 22 | 23 | public String code() { 24 | return code; 25 | } 26 | 27 | public OauthCode code(String code) { 28 | this.code = code; 29 | return this; 30 | } 31 | 32 | public String username() { 33 | return username; 34 | } 35 | 36 | public OauthCode username(String username) { 37 | this.username = username; 38 | return this; 39 | } 40 | 41 | public String clientId() { 42 | return clientId; 43 | } 44 | 45 | public OauthCode clientId(String clientId) { 46 | this.clientId = clientId; 47 | return this; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /core/src/main/java/com/monkeyk/os/domain/AbstractDomain.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.domain; 2 | 3 | import com.monkeyk.os.infrastructure.DateUtils; 4 | 5 | import java.io.Serializable; 6 | import java.util.Date; 7 | 8 | /** 9 | * 抽象的Domain实体类, 基于DDD设计模式 10 | * 11 | * @author Shengzhao Li 12 | * @serial 13 | */ 14 | public abstract class AbstractDomain implements Serializable { 15 | 16 | 17 | private static final long serialVersionUID = 7787898374385773471L; 18 | 19 | /** 20 | * 创建时间, 默认为当前时间值 21 | */ 22 | protected Date createTime = DateUtils.now(); 23 | 24 | public AbstractDomain() { 25 | } 26 | 27 | 28 | public Date createTime() { 29 | return createTime; 30 | } 31 | 32 | /** 33 | * 设置Domain的创建时间并返回实体本身. 34 | * Builder设计模式的变种 35 | * 36 | * @param createTime createTime 37 | * @param AbstractDomain subclass 38 | * @return Current domain 39 | */ 40 | @SuppressWarnings("unchecked") 41 | public T createTime(Date createTime) { 42 | this.createTime = createTime; 43 | return (T) this; 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /core/src/main/java/com/monkeyk/os/oauth/shiro/OAuth2SubjectFactory.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.oauth.shiro; 2 | 3 | import org.apache.shiro.authc.AuthenticationToken; 4 | import org.apache.shiro.subject.Subject; 5 | import org.apache.shiro.subject.SubjectContext; 6 | import org.apache.shiro.web.mgt.DefaultWebSubjectFactory; 7 | 8 | /** 9 | * 2015/9/29 10 | *

11 | * See CasSubjectFactory 12 | * 13 | * @author Shengzhao Li 14 | */ 15 | public class OAuth2SubjectFactory extends DefaultWebSubjectFactory { 16 | 17 | 18 | @Override 19 | public Subject createSubject(SubjectContext context) { 20 | 21 | 22 | boolean authenticated = context.isAuthenticated(); 23 | 24 | if (authenticated) { 25 | 26 | AuthenticationToken token = context.getAuthenticationToken(); 27 | 28 | if (token != null && token instanceof OAuth2Token) { 29 | OAuth2Token oAuth2Token = (OAuth2Token) token; 30 | if (oAuth2Token.isRememberMe()) { 31 | context.setAuthenticated(false); 32 | } 33 | } 34 | } 35 | 36 | return super.createSubject(context); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /authz/src/test/java/com/monkeyk/os/domain/oauth/AuthenticationIdGeneratorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Andaily Information Technology Co. Ltd 3 | * www.andaily.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * Andaily Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with Andaily Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.domain.oauth; 13 | 14 | import org.testng.annotations.Test; 15 | 16 | import static org.testng.Assert.assertNotNull; 17 | 18 | /** 19 | * 15-6-20 20 | * 21 | * @author Shengzhao Li 22 | */ 23 | public class AuthenticationIdGeneratorTest { 24 | 25 | @Test 26 | public void testGenerate() throws Exception { 27 | 28 | DefaultAuthenticationIdGenerator generator = new DefaultAuthenticationIdGenerator(); 29 | final String generate = generator.generate("clientid", "username", "authid"); 30 | 31 | assertNotNull(generate); 32 | System.out.println(generate); 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /core/src/main/java/com/monkeyk/os/infrastructure/shiro/MkkJdbcRealm.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.infrastructure.shiro; 2 | 3 | import org.apache.shiro.realm.jdbc.JdbcRealm; 4 | import org.springframework.beans.factory.InitializingBean; 5 | 6 | /** 7 | * 15-6-10 8 | * 9 | * @author Shengzhao Li 10 | */ 11 | public class MkkJdbcRealm extends JdbcRealm implements InitializingBean { 12 | 13 | public static final String AUTHENTICATION_QUERY = "select password from users where archived = 0 and username = ?"; 14 | 15 | public static final String USER_ROLES_QUERY = "select r.role_name from user_roles ur,users u,roles r where ur.users_id = u.id and ur.roles_id = r.id and u.username = ?"; 16 | 17 | public static final String PERMISSIONS_QUERY = "select rp.permission from roles_permissions rp,roles r where r.id = rp.roles_id and r.role_name = ?"; 18 | 19 | 20 | public MkkJdbcRealm() { 21 | super(); 22 | } 23 | 24 | 25 | @Override 26 | public void afterPropertiesSet() throws Exception { 27 | //override 28 | setAuthenticationQuery(AUTHENTICATION_QUERY); 29 | setUserRolesQuery(USER_ROLES_QUERY); 30 | setPermissionsQuery(PERMISSIONS_QUERY); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/oauth/token/OAuthTokenHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Andaily Information Technology Co. Ltd 3 | * www.andaily.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * Andaily Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with Andaily Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.oauth.token; 13 | 14 | import com.monkeyk.os.oauth.OAuthTokenxRequest; 15 | import org.apache.oltu.oauth2.common.exception.OAuthProblemException; 16 | import org.apache.oltu.oauth2.common.exception.OAuthSystemException; 17 | 18 | import javax.servlet.http.HttpServletResponse; 19 | 20 | /** 21 | * 2015/7/3 22 | * 23 | * @author Shengzhao Li 24 | */ 25 | 26 | public interface OAuthTokenHandler { 27 | 28 | 29 | boolean support(OAuthTokenxRequest tokenRequest) throws OAuthProblemException; 30 | 31 | void handle(OAuthTokenxRequest tokenRequest, HttpServletResponse response) throws OAuthProblemException, OAuthSystemException; 32 | 33 | 34 | } -------------------------------------------------------------------------------- /resources/src/main/java/com/monkeyk/os/domain/rs/OAuthRSCacheRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.domain.rs; 13 | 14 | import com.monkeyk.os.domain.oauth.AccessToken; 15 | import com.monkeyk.os.domain.oauth.ClientDetails; 16 | import com.monkeyk.os.domain.shared.Repository; 17 | 18 | /** 19 | * 2015/10/26 20 | *

21 | *

22 | * Wrapper OAuthRSRepository, add cache support 23 | * 24 | * @author Shengzhao Li 25 | * @see com.monkeyk.os.domain.rs.OAuthRSRepository 26 | */ 27 | public interface OAuthRSCacheRepository extends Repository { 28 | 29 | 30 | AccessToken findAccessTokenByTokenId(String tokenId); 31 | 32 | ClientDetails findClientDetailsByClientIdAndResourceIds(String clientId, String resourceIds); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/web/context/MkkCharacterEncodingFilter.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.web.context; 2 | 3 | import com.monkeyk.os.infrastructure.ThreadLocalHolder; 4 | import com.monkeyk.os.web.WebUtils; 5 | import org.springframework.web.filter.CharacterEncodingFilter; 6 | 7 | import javax.servlet.FilterChain; 8 | import javax.servlet.ServletException; 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletResponse; 11 | import java.io.IOException; 12 | 13 | /** 14 | * Wrap the spring CharacterEncodingFilter, add retrieve client ip action 15 | * 16 | * @author Shengzhao Li 17 | */ 18 | public class MkkCharacterEncodingFilter extends CharacterEncodingFilter { 19 | 20 | 21 | @Override 22 | protected void doFilterInternal( 23 | HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) 24 | throws ServletException, IOException { 25 | 26 | persistIp(request); 27 | super.doFilterInternal(request, response, filterChain); 28 | 29 | } 30 | 31 | private void persistIp(HttpServletRequest request) { 32 | final String clientIp = WebUtils.retrieveClientIp(request); 33 | ThreadLocalHolder.clientIp(clientIp); 34 | } 35 | 36 | 37 | } -------------------------------------------------------------------------------- /resources/src/main/java/com/monkeyk/os/web/context/MkkCharacterEncodingFilter.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.web.context; 2 | 3 | import com.monkeyk.os.infrastructure.ThreadLocalHolder; 4 | import com.monkeyk.os.web.WebUtils; 5 | import org.springframework.web.filter.CharacterEncodingFilter; 6 | 7 | import javax.servlet.FilterChain; 8 | import javax.servlet.ServletException; 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletResponse; 11 | import java.io.IOException; 12 | 13 | /** 14 | * Wrap the spring CharacterEncodingFilter, add retrieve client ip action 15 | * 16 | * @author Shengzhao Li 17 | */ 18 | public class MkkCharacterEncodingFilter extends CharacterEncodingFilter { 19 | 20 | 21 | @Override 22 | protected void doFilterInternal( 23 | HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) 24 | throws ServletException, IOException { 25 | 26 | persistIp(request); 27 | super.doFilterInternal(request, response, filterChain); 28 | 29 | } 30 | 31 | private void persistIp(HttpServletRequest request) { 32 | final String clientIp = WebUtils.retrieveClientIp(request); 33 | ThreadLocalHolder.clientIp(clientIp); 34 | } 35 | 36 | 37 | } -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/oauth/OAuthTokenxRequest.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.oauth; 2 | 3 | import org.apache.oltu.oauth2.as.request.OAuthTokenRequest; 4 | import org.apache.oltu.oauth2.common.exception.OAuthProblemException; 5 | import org.apache.oltu.oauth2.common.exception.OAuthSystemException; 6 | 7 | import javax.servlet.http.HttpServletRequest; 8 | 9 | /** 10 | * 2015/7/3 11 | *

12 | * Ext OAuthTokenRequest 13 | * 14 | * @author Shengzhao Li 15 | */ 16 | public class OAuthTokenxRequest extends OAuthTokenRequest { 17 | 18 | /** 19 | * Create an OAuth Token request from a given HttpSerlvetRequest 20 | * 21 | * @param request the httpservletrequest that is validated and transformed into the OAuth Token Request 22 | * @throws org.apache.oltu.oauth2.common.exception.OAuthSystemException if an unexpected exception was thrown 23 | * @throws org.apache.oltu.oauth2.common.exception.OAuthProblemException if the request was not a valid Token request this exception is thrown. 24 | */ 25 | public OAuthTokenxRequest(HttpServletRequest request) throws OAuthSystemException, OAuthProblemException { 26 | super(request); 27 | } 28 | 29 | public HttpServletRequest request() { 30 | return this.request; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /core/src/main/java/com/monkeyk/os/infrastructure/jdbc/UserRolesRowMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.infrastructure.jdbc; 13 | 14 | 15 | import com.monkeyk.os.domain.users.UserRoles; 16 | import org.springframework.jdbc.core.RowMapper; 17 | 18 | import java.sql.ResultSet; 19 | import java.sql.SQLException; 20 | 21 | /** 22 | * 2015/10/26 23 | * 24 | * @author Shengzhao Li 25 | */ 26 | public class UserRolesRowMapper implements RowMapper { 27 | 28 | 29 | @Override 30 | public UserRoles mapRow(ResultSet rs, int rowNum) throws SQLException { 31 | UserRoles roles = new UserRoles(); 32 | 33 | roles.createTime(rs.getTimestamp("create_time")); 34 | roles.usersId(rs.getInt("users_id")); 35 | roles.rolesId(rs.getInt("roles_id")); 36 | 37 | return roles; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /authz/src/main/webapp/WEB-INF/jsp/decorators/main.jsp: -------------------------------------------------------------------------------- 1 | <%-- 2 | * 3 | * @author Shengzhao Li 4 | --%> 5 | 6 | <%@ page contentType="text/html;charset=UTF-8" language="java" %> 7 | <%@ taglib uri="http://www.opensymphony.com/sitemesh/decorator" prefix="decorator" %> 8 | <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | <decorator:title default=""/> | Oauth2-Shiro[authz] 20 | 21 | 22 | 23 | 24 | 25 | 26 |

27 | 28 | 29 |
30 |
31 |
32 |
33 | © oauth2-shiro 34 |
35 |
36 |
37 |
38 | 39 | -------------------------------------------------------------------------------- /authz/src/main/webapp/WEB-INF/jsp/index.jsp: -------------------------------------------------------------------------------- 1 | <%-- 2 | * 3 | * @author Shengzhao Li 4 | --%> 5 | 6 | <%@ page contentType="text/html;charset=UTF-8" language="java" %> 7 | <%@ include file="comm-header.jsp" %> 8 | 9 | 10 | 11 | Home 12 | 13 | 14 |

Oauth2-Shiro is work!

15 | Logout 16 |
17 | Welcome: 18 |
19 |
20 | Oauth 21 | 22 |

23 | oauth_test 24 |

25 |
26 |
27 |
28 | Menus 29 | 30 |

Test different roles show different menus

31 | 45 |
46 | 47 | -------------------------------------------------------------------------------- /core/src/main/java/com/monkeyk/os/infrastructure/jdbc/AccessTokenRowMapper.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.infrastructure.jdbc; 2 | 3 | import com.monkeyk.os.domain.oauth.AccessToken; 4 | import org.springframework.jdbc.core.RowMapper; 5 | 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | 9 | /** 10 | * 15-6-20 11 | * 12 | * @author Shengzhao Li 13 | */ 14 | public class AccessTokenRowMapper implements RowMapper { 15 | 16 | 17 | public AccessTokenRowMapper() { 18 | } 19 | 20 | @Override 21 | public AccessToken mapRow(ResultSet rs, int rowNum) throws SQLException { 22 | final AccessToken oauthCode = new AccessToken() 23 | .tokenId(rs.getString("token_id")) 24 | .tokenExpiredSeconds(rs.getInt("token_expired_seconds")) 25 | .authenticationId(rs.getString("authentication_id")) 26 | 27 | .username(rs.getString("username")) 28 | .clientId(rs.getString("client_id")) 29 | .tokenType(rs.getString("token_type")) 30 | 31 | .refreshTokenExpiredSeconds(rs.getInt("refresh_token_expired_seconds")) 32 | .refreshToken(rs.getString("refresh_token")); 33 | 34 | oauthCode.createTime(rs.getTimestamp("create_time")); 35 | 36 | 37 | return oauthCode; 38 | 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /resources/src/test/java/com/monkeyk/os/infrastructure/jdbc/OAuthRSJdbcRepositoryTest.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.infrastructure.jdbc; 2 | 3 | import com.monkeyk.os.ContextTest; 4 | import com.monkeyk.os.domain.oauth.AccessToken; 5 | import com.monkeyk.os.domain.oauth.ClientDetails; 6 | import com.monkeyk.os.domain.oauth.OauthCode; 7 | import com.monkeyk.os.domain.shared.GuidGenerator; 8 | import org.springframework.beans.factory.annotation.Autowired; 9 | import org.testng.annotations.Test; 10 | 11 | import static org.testng.Assert.*; 12 | 13 | /** 14 | * 15-6-13 15 | * 16 | * @author Shengzhao Li 17 | */ 18 | public class OAuthRSJdbcRepositoryTest extends ContextTest { 19 | 20 | @Autowired 21 | private OAuthRSJdbcRepository oauthJdbcRepository; 22 | 23 | 24 | @Test 25 | public void findAccessTokenByTokenId() throws Exception { 26 | String tokenId = GuidGenerator.generate(); 27 | 28 | final AccessToken accessToken = oauthJdbcRepository.findAccessTokenByTokenId(tokenId); 29 | assertNull(accessToken); 30 | 31 | } 32 | 33 | @Test 34 | public void findClientDetailsByClientIdAndResourceIds() throws Exception { 35 | 36 | final ClientDetails clientDetails = oauthJdbcRepository.findClientDetailsByClientIdAndResourceIds("clientId", "resourceId"); 37 | assertNull(clientDetails); 38 | 39 | } 40 | 41 | 42 | } 43 | -------------------------------------------------------------------------------- /core/src/main/java/com/monkeyk/os/infrastructure/jdbc/RolesPermissionsRowMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.infrastructure.jdbc; 13 | 14 | import com.monkeyk.os.domain.users.RolesPermissions; 15 | import org.springframework.jdbc.core.RowMapper; 16 | 17 | import java.sql.ResultSet; 18 | import java.sql.SQLException; 19 | 20 | /** 21 | * 2015/10/26 22 | * 23 | * @author Shengzhao Li 24 | */ 25 | public class RolesPermissionsRowMapper implements RowMapper { 26 | 27 | 28 | @Override 29 | public RolesPermissions mapRow(ResultSet rs, int rowNum) throws SQLException { 30 | RolesPermissions permissions = new RolesPermissions(); 31 | 32 | permissions.createTime(rs.getTimestamp("create_time")); 33 | permissions.rolesId(rs.getInt("roles_id")); 34 | permissions.permission(rs.getString("permission")); 35 | 36 | return permissions; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /resources/src/main/java/com/monkeyk/os/service/impl/OAuthRSServiceImpl.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.service.impl; 2 | 3 | import com.monkeyk.os.domain.oauth.AccessToken; 4 | import com.monkeyk.os.domain.oauth.ClientDetails; 5 | import com.monkeyk.os.domain.rs.OAuthRSCacheRepository; 6 | import com.monkeyk.os.service.OAuthRSService; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.beans.factory.annotation.Autowired; 10 | import org.springframework.stereotype.Service; 11 | 12 | /** 13 | * 2015/7/8 14 | * 15 | * @author Shengzhao Li 16 | */ 17 | @Service("oAuthRSService") 18 | public class OAuthRSServiceImpl implements OAuthRSService { 19 | 20 | 21 | private static final Logger LOG = LoggerFactory.getLogger(OAuthRSServiceImpl.class); 22 | 23 | 24 | @Autowired 25 | private OAuthRSCacheRepository oAuthRSRepository; 26 | 27 | 28 | @Override 29 | public AccessToken loadAccessTokenByTokenId(String tokenId) { 30 | return oAuthRSRepository.findAccessTokenByTokenId(tokenId); 31 | } 32 | 33 | 34 | @Override 35 | public ClientDetails loadClientDetails(String clientId, String resourceIds) { 36 | LOG.debug("Load ClientDetails by clientId: {}, resourceIds: {}", clientId, resourceIds); 37 | return oAuthRSRepository.findClientDetailsByClientIdAndResourceIds(clientId, resourceIds); 38 | } 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /authz/src/test/java/com/monkeyk/os/domain/oauth/AccessTokenTest.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.domain.oauth; 2 | 3 | import com.monkeyk.os.infrastructure.DateUtils; 4 | import org.testng.annotations.Test; 5 | 6 | import java.net.URLDecoder; 7 | import java.net.URLEncoder; 8 | 9 | import static org.testng.Assert.assertFalse; 10 | import static org.testng.Assert.assertTrue; 11 | 12 | /** 13 | * @author Shengzhao Li 14 | */ 15 | public class AccessTokenTest { 16 | 17 | 18 | @Test 19 | public void decode() throws Exception { 20 | 21 | String url = "http://localhost:7777/spring-oauth-client/authorization_code_callback"; 22 | final String decode = URLEncoder.encode(url, "UTF-8"); 23 | System.out.println(decode); 24 | } 25 | 26 | 27 | @Test 28 | public void refreshTokenExpired() { 29 | 30 | 31 | AccessToken token = new AccessToken(); 32 | 33 | token.createTime(DateUtils.getDate("2015-01-01 12:12:12", DateUtils.DEFAULT_DATE_TIME_FORMAT)); 34 | token.tokenExpiredSeconds(10); 35 | 36 | assertTrue(token.refreshTokenExpired()); 37 | 38 | 39 | token.createTime(DateUtils.now()); 40 | token.tokenExpiredSeconds(12); 41 | 42 | assertFalse(token.refreshTokenExpired()); 43 | 44 | 45 | token.createTime(DateUtils.now()); 46 | token.tokenExpiredSeconds(0); 47 | 48 | assertFalse(token.refreshTokenExpired()); 49 | 50 | 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/service/dto/LoginDto.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Andaily Information Technology Co. Ltd 3 | * www.andaily.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * Andaily Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with Andaily Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.service.dto; 13 | 14 | import org.apache.shiro.authc.UsernamePasswordToken; 15 | 16 | import java.io.Serializable; 17 | 18 | /** 19 | * 15-6-10 20 | * 21 | * @author Shengzhao Li 22 | */ 23 | public class LoginDto implements Serializable { 24 | 25 | 26 | private String username; 27 | private String password; 28 | 29 | public LoginDto() { 30 | } 31 | 32 | public UsernamePasswordToken token() { 33 | return new UsernamePasswordToken(username, password); 34 | } 35 | 36 | public String getUsername() { 37 | return username; 38 | } 39 | 40 | public void setUsername(String username) { 41 | this.username = username; 42 | } 43 | 44 | public String getPassword() { 45 | return password; 46 | } 47 | 48 | public void setPassword(String password) { 49 | this.password = password; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /core/src/main/java/com/monkeyk/os/infrastructure/jdbc/RolesRowMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.infrastructure.jdbc; 13 | 14 | import com.monkeyk.os.domain.users.Roles; 15 | 16 | import org.springframework.jdbc.core.RowMapper; 17 | 18 | import java.sql.ResultSet; 19 | import java.sql.SQLException; 20 | 21 | /** 22 | * 2015/10/26 23 | * 24 | * @author Shengzhao Li 25 | */ 26 | public class RolesRowMapper implements RowMapper { 27 | 28 | 29 | @Override 30 | public Roles mapRow(ResultSet rs, int rowNum) throws SQLException { 31 | Roles roles = new Roles(); 32 | 33 | roles.id(rs.getInt("id")) 34 | .guid(rs.getString("guid")) 35 | .version(rs.getInt("version")) 36 | .archived(rs.getBoolean("archived")); 37 | 38 | roles.createTime(rs.getTimestamp("create_time")); 39 | 40 | roles.roleName(rs.getString("role_name")); 41 | 42 | return roles; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /resources/src/test/java/com/monkeyk/os/domain/oauth/AccessTokenTest.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.domain.oauth; 2 | 3 | import com.monkeyk.os.infrastructure.DateUtils; 4 | import org.testng.annotations.Test; 5 | 6 | import java.net.URLDecoder; 7 | import java.net.URLEncoder; 8 | 9 | import static org.testng.Assert.assertFalse; 10 | import static org.testng.Assert.assertTrue; 11 | 12 | /** 13 | * @author Shengzhao Li 14 | */ 15 | public class AccessTokenTest { 16 | 17 | 18 | @Test 19 | public void decode() throws Exception { 20 | 21 | String url = "http://localhost:7777/spring-oauth-client/authorization_code_callback"; 22 | final String decode = URLEncoder.encode(url, "UTF-8"); 23 | System.out.println(decode); 24 | } 25 | 26 | 27 | @Test 28 | public void refreshTokenExpired() { 29 | 30 | 31 | AccessToken token = new AccessToken(); 32 | 33 | token.createTime(DateUtils.getDate("2015-01-01 12:12:12", DateUtils.DEFAULT_DATE_TIME_FORMAT)); 34 | token.tokenExpiredSeconds(10); 35 | 36 | assertTrue(token.refreshTokenExpired()); 37 | 38 | 39 | token.createTime(DateUtils.now()); 40 | token.tokenExpiredSeconds(12); 41 | 42 | assertFalse(token.refreshTokenExpired()); 43 | 44 | 45 | token.createTime(DateUtils.now()); 46 | token.tokenExpiredSeconds(0); 47 | 48 | assertFalse(token.refreshTokenExpired()); 49 | 50 | 51 | } 52 | 53 | } -------------------------------------------------------------------------------- /core/src/main/java/com/monkeyk/os/infrastructure/cache/CacheNames.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.infrastructure.cache; 13 | 14 | /** 15 | * 2015/10/21 16 | * 17 | * @author Shengzhao Li 18 | */ 19 | public abstract class CacheNames { 20 | 21 | 22 | /** 23 | * AccessToken cache 24 | * key: tokenId 25 | */ 26 | public static final String ACCESS_TOKEN_CACHE = "accessTokenCache"; 27 | 28 | 29 | /** 30 | * ClientDetails cache 31 | * key: clientId + cache_name 32 | */ 33 | public static final String CLIENT_DETAILS_CACHE = "clientDetailsCache"; 34 | 35 | 36 | /** 37 | * User cache 38 | */ 39 | public static final String USERS_CACHE = "usersCache"; 40 | 41 | 42 | /** 43 | * OauthCode cache 44 | * key: code + clientId 45 | */ 46 | public static final String OAUTH_CODE_CACHE = "oauthCodeCache"; 47 | 48 | 49 | //private 50 | private CacheNames() { 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /core/src/main/java/com/monkeyk/os/domain/users/Roles.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.domain.users; 13 | 14 | import com.monkeyk.os.domain.AbstractIdDomain; 15 | 16 | import java.util.HashSet; 17 | import java.util.Set; 18 | 19 | /** 20 | * 2015/10/26 21 | *

22 | * Table: roles 23 | * 24 | * @author Shengzhao Li 25 | */ 26 | public class Roles extends AbstractIdDomain { 27 | 28 | 29 | private static final long serialVersionUID = 8762398291767207066L; 30 | 31 | //unique 32 | private String roleName; 33 | 34 | //permission 35 | private Set permissions = new HashSet<>(); 36 | 37 | 38 | public Roles() { 39 | } 40 | 41 | public Set permissions() { 42 | return permissions; 43 | } 44 | 45 | public String roleName() { 46 | return roleName; 47 | } 48 | 49 | public Roles roleName(String roleName) { 50 | this.roleName = roleName; 51 | return this; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /core/src/main/java/com/monkeyk/os/domain/users/UserRoles.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.domain.users; 13 | 14 | import com.monkeyk.os.domain.AbstractDomain; 15 | 16 | 17 | import java.util.HashSet; 18 | import java.util.Set; 19 | 20 | /** 21 | * 2015/10/26 22 | *

23 | * Table: user_roles 24 | * 25 | * @author Shengzhao Li 26 | */ 27 | public class UserRoles extends AbstractDomain { 28 | 29 | private static final long serialVersionUID = 8722613219109153850L; 30 | 31 | private int usersId; 32 | 33 | // roles_id 34 | private int rolesId; 35 | 36 | 37 | public UserRoles() { 38 | } 39 | 40 | public int usersId() { 41 | return usersId; 42 | } 43 | 44 | public UserRoles usersId(int usersId) { 45 | this.usersId = usersId; 46 | return this; 47 | } 48 | 49 | public int rolesId() { 50 | return rolesId; 51 | } 52 | 53 | public UserRoles rolesId(int rolesId) { 54 | this.rolesId = rolesId; 55 | return this; 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /core/src/main/java/com/monkeyk/os/domain/users/RolesPermissions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.domain.users; 13 | 14 | import com.monkeyk.os.domain.AbstractDomain; 15 | 16 | /** 17 | * 2015/10/26 18 | *

19 | * Table: roles_permissions 20 | * 21 | * @author Shengzhao Li 22 | */ 23 | public class RolesPermissions extends AbstractDomain { 24 | 25 | private static final long serialVersionUID = 4919225497795040502L; 26 | 27 | 28 | // Refer to Roles 29 | private int rolesId; 30 | 31 | private String permission; 32 | 33 | 34 | public RolesPermissions() { 35 | } 36 | 37 | public int rolesId() { 38 | return rolesId; 39 | } 40 | 41 | public RolesPermissions rolesId(int rolesId) { 42 | this.rolesId = rolesId; 43 | return this; 44 | } 45 | 46 | public String permission() { 47 | return permission; 48 | } 49 | 50 | public RolesPermissions permission(String permission) { 51 | this.permission = permission; 52 | return this; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/service/business/AbstractOAuthHolder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.service.business; 13 | 14 | import com.monkeyk.os.domain.oauth.OauthCacheRepository; 15 | import com.monkeyk.os.domain.shared.BeanProvider; 16 | import org.apache.oltu.oauth2.as.issuer.OAuthIssuer; 17 | import org.apache.shiro.SecurityUtils; 18 | 19 | /** 20 | * 2015/10/22 21 | * 22 | * @author Shengzhao Li 23 | */ 24 | public abstract class AbstractOAuthHolder { 25 | 26 | 27 | // protected transient OauthRepository oauthRepository = BeanProvider.getBean(OauthRepository.class); 28 | 29 | protected transient OauthCacheRepository oauthRepository = BeanProvider.getBean(OauthCacheRepository.class); 30 | 31 | 32 | protected transient OAuthIssuer oAuthIssuer = BeanProvider.getBean(OAuthIssuer.class); 33 | 34 | /** 35 | * Return current login username 36 | * 37 | * @return Username 38 | */ 39 | protected String currentUsername() { 40 | return (String) SecurityUtils.getSubject().getPrincipal(); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/domain/oauth/OauthCacheRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.domain.oauth; 13 | 14 | 15 | import com.monkeyk.os.domain.shared.Repository; 16 | 17 | /** 18 | * 2015/10/22 19 | *

20 | * Wrapper OauthRepository, and add cache support 21 | * 22 | * @author Shengzhao Li 23 | * @see OauthRepository 24 | */ 25 | 26 | public interface OauthCacheRepository extends Repository { 27 | 28 | 29 | int saveOauthCode(OauthCode oauthCode); 30 | 31 | OauthCode findOauthCodeByUsernameClientId(String username, String clientId); 32 | 33 | int deleteOauthCode(OauthCode oauthCode); 34 | 35 | int saveAccessToken(AccessToken accessToken); 36 | 37 | AccessToken findAccessToken(String clientId, String username, String authenticationId); 38 | 39 | int deleteAccessToken(AccessToken accessToken); 40 | 41 | OauthCode findOauthCode(String code, String clientId); 42 | 43 | AccessToken findAccessTokenByRefreshToken(String refreshToken, String clientId); 44 | 45 | ClientDetails findClientDetails(String clientId); 46 | } -------------------------------------------------------------------------------- /authz/src/test/java/com/monkeyk/os/infrastructure/jdbc/UsersJdbcRepositoryTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.infrastructure.jdbc; 13 | 14 | import com.monkeyk.os.ContextTest; 15 | import com.monkeyk.os.domain.users.Roles; 16 | import com.monkeyk.os.domain.users.Users; 17 | import org.springframework.beans.factory.annotation.Autowired; 18 | import org.testng.annotations.Test; 19 | 20 | import java.util.List; 21 | 22 | import static org.testng.Assert.*; 23 | 24 | /* 25 | * @author Shengzhao Li 26 | */ 27 | public class UsersJdbcRepositoryTest extends ContextTest { 28 | 29 | 30 | @Autowired 31 | private UsersJdbcRepository usersJdbcRepository; 32 | 33 | 34 | @Test 35 | public void findUsersByUsername() { 36 | 37 | final Users users = usersJdbcRepository.findUsersByUsername("abc"); 38 | assertNull(users); 39 | } 40 | 41 | 42 | @Test 43 | public void findRolesByUsername() { 44 | 45 | final List list = usersJdbcRepository.findRolesByUsername("abcd"); 46 | assertTrue(list.isEmpty()); 47 | } 48 | 49 | } -------------------------------------------------------------------------------- /core/src/main/java/com/monkeyk/os/oauth/shiro/OAuth2Token.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.oauth.shiro; 2 | 3 | import org.apache.shiro.authc.RememberMeAuthenticationToken; 4 | 5 | /** 6 | * 2015/9/29 7 | * 8 | * @author Shengzhao Li 9 | */ 10 | public class OAuth2Token implements RememberMeAuthenticationToken { 11 | 12 | 13 | private static final long serialVersionUID = 8587854556973099598L; 14 | 15 | 16 | // the service access_token 17 | private String accessToken; 18 | 19 | // the user identifier, username 20 | private String userId; 21 | 22 | // is the user in a remember me mode ? 23 | private boolean rememberMe = false; 24 | 25 | 26 | private String resourceId; 27 | 28 | 29 | public OAuth2Token(String accessToken, String resourceId) { 30 | this.accessToken = accessToken; 31 | this.resourceId = resourceId; 32 | } 33 | 34 | public String getResourceId() { 35 | return resourceId; 36 | } 37 | 38 | @Override 39 | public boolean isRememberMe() { 40 | return rememberMe; 41 | } 42 | 43 | public OAuth2Token setUserId(String userId) { 44 | this.userId = userId; 45 | return this; 46 | } 47 | 48 | public OAuth2Token setRememberMe(boolean rememberMe) { 49 | this.rememberMe = rememberMe; 50 | return this; 51 | } 52 | 53 | @Override 54 | public Object getPrincipal() { 55 | return userId; 56 | } 57 | 58 | @Override 59 | public Object getCredentials() { 60 | return accessToken; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /resources/src/main/java/com/monkeyk/os/infrastructure/jdbc/OAuthRSJdbcRepository.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.infrastructure.jdbc; 2 | 3 | import com.monkeyk.os.domain.oauth.AccessToken; 4 | import com.monkeyk.os.domain.oauth.ClientDetails; 5 | 6 | import com.monkeyk.os.domain.rs.OAuthRSRepository; 7 | import org.springframework.stereotype.Repository; 8 | 9 | import java.util.List; 10 | 11 | /** 12 | * 15-6-13 13 | * 14 | * @author Shengzhao Li 15 | */ 16 | @Repository("oauthRSJdbcRepository") 17 | public class OAuthRSJdbcRepository extends AbstractJdbcRepository implements OAuthRSRepository { 18 | 19 | 20 | private static ClientDetailsRowMapper clientDetailsRowMapper = new ClientDetailsRowMapper(); 21 | private AccessTokenRowMapper accessTokenRowMapper = new AccessTokenRowMapper(); 22 | 23 | 24 | @Override 25 | public AccessToken findAccessTokenByTokenId(String tokenId) { 26 | final String sql = " select * from oauth_access_token where token_id = ?"; 27 | final List list = jdbcTemplate.query(sql, accessTokenRowMapper, tokenId); 28 | return list.isEmpty() ? null : list.get(0); 29 | } 30 | 31 | @Override 32 | public ClientDetails findClientDetailsByClientIdAndResourceIds(String clientId, String resourceIds) { 33 | final String sql = " select * from oauth_client_details where archived = 0 and client_id = ? and resource_ids = ? "; 34 | final List list = jdbcTemplate.query(sql, clientDetailsRowMapper, clientId, resourceIds); 35 | return list.isEmpty() ? null : list.get(0); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /resources/src/test/java/com/monkeyk/os/infrastructure/UsersRSRedisRepositoryTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.infrastructure; 13 | 14 | import com.monkeyk.os.ContextTest; 15 | import com.monkeyk.os.domain.users.Roles; 16 | import com.monkeyk.os.domain.users.Users; 17 | import com.monkeyk.os.infrastructure.jdbc.UsersRSJdbcRepository; 18 | import org.springframework.beans.factory.annotation.Autowired; 19 | import org.testng.annotations.Test; 20 | 21 | import java.util.List; 22 | 23 | import static org.testng.Assert.*; 24 | 25 | /* 26 | * @author Shengzhao Li 27 | */ 28 | public class UsersRSRedisRepositoryTest extends ContextTest { 29 | 30 | 31 | @Autowired 32 | private UsersRSJdbcRepository usersJdbcRepository; 33 | 34 | 35 | @Test 36 | public void findUsersByUsername() { 37 | 38 | final Users users = usersJdbcRepository.findUsersByUsername("abc"); 39 | assertNull(users); 40 | } 41 | 42 | 43 | @Test 44 | public void findRolesByUsername() { 45 | 46 | final List list = usersJdbcRepository.findRolesByUsername("abcd"); 47 | assertTrue(list.isEmpty()); 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /core/src/main/java/com/monkeyk/os/infrastructure/jdbc/UsersRowMapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.infrastructure.jdbc; 13 | 14 | 15 | import com.monkeyk.os.domain.users.Users; 16 | import org.springframework.jdbc.core.RowMapper; 17 | 18 | import java.sql.ResultSet; 19 | import java.sql.SQLException; 20 | 21 | /** 22 | * 2015/10/26 23 | * 24 | * @author Shengzhao Li 25 | */ 26 | public class UsersRowMapper implements RowMapper { 27 | 28 | 29 | @Override 30 | public Users mapRow(ResultSet rs, int rowNum) throws SQLException { 31 | Users users = new Users(); 32 | 33 | users.id(rs.getInt("id")) 34 | .guid(rs.getString("guid")) 35 | .version(rs.getInt("version")) 36 | .archived(rs.getBoolean("archived")); 37 | 38 | users.createTime(rs.getTimestamp("create_time")); 39 | 40 | users.username(rs.getString("username")) 41 | .password(rs.getString("password")) 42 | .defaultUser(rs.getBoolean("default_user")) 43 | .lastLoginTime(rs.getTimestamp("last_login_time")); 44 | 45 | return users; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | monkeyk.com 8 | oauth2-shiro-redis 9 | 0.1 10 | 11 | ${project.artifactId} 12 | pom 13 | oltu and shiro(Redis) 14 | 15 | 16 | UTF-8 17 | 18 | 19 | 20 | 21 | 22 | shengzhao 23 | sz@monkeyk.com 24 | 25 | 26 | 27 | 28 | 29 | core 30 | authz 31 | resources 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | maven-compiler-plugin 40 | 3.2 41 | 42 | 1.7 43 | 1.7 44 | UTF-8 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /resources/src/main/java/com/monkeyk/os/oauth/resources/MkkOAuthDecision.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.oauth.resources; 2 | 3 | import com.monkeyk.os.domain.rs.RSOAuthClient; 4 | import org.apache.oltu.oauth2.rsfilter.OAuthClient; 5 | import org.apache.oltu.oauth2.rsfilter.OAuthDecision; 6 | 7 | import java.security.Principal; 8 | 9 | /** 10 | * 2015/7/8 11 | * 12 | * @author Shengzhao Li 13 | */ 14 | public class MkkOAuthDecision implements OAuthDecision { 15 | 16 | 17 | private boolean authorized; 18 | 19 | private Principal principal; 20 | 21 | private RSOAuthClient oAuthClient; 22 | 23 | public MkkOAuthDecision() { 24 | } 25 | 26 | @Override 27 | public boolean isAuthorized() { 28 | return authorized; 29 | } 30 | 31 | @Override 32 | public Principal getPrincipal() { 33 | return principal; 34 | } 35 | 36 | @Override 37 | public OAuthClient getOAuthClient() { 38 | return oAuthClient; 39 | } 40 | 41 | public MkkOAuthDecision setPrincipal(Principal principal) { 42 | this.principal = principal; 43 | return this; 44 | } 45 | 46 | public MkkOAuthDecision setOAuthClient(RSOAuthClient oAuthClient) { 47 | this.oAuthClient = oAuthClient; 48 | return this; 49 | } 50 | 51 | public MkkOAuthDecision setAuthorized(boolean authorized) { 52 | this.authorized = authorized; 53 | return this; 54 | } 55 | 56 | @Override 57 | public String toString() { 58 | return "{" + 59 | "authorized=" + authorized + 60 | ", principal=" + principal + 61 | ", oAuthClient=" + oAuthClient + 62 | '}'; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /core/src/main/java/com/monkeyk/os/infrastructure/jdbc/ClientDetailsRowMapper.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.infrastructure.jdbc; 2 | 3 | import com.monkeyk.os.domain.oauth.ClientDetails; 4 | import org.springframework.jdbc.core.RowMapper; 5 | 6 | import java.sql.ResultSet; 7 | import java.sql.SQLException; 8 | 9 | /** 10 | * 15-6-13 11 | * 12 | * @author Shengzhao Li 13 | */ 14 | public class ClientDetailsRowMapper implements RowMapper { 15 | 16 | 17 | public ClientDetailsRowMapper() { 18 | } 19 | 20 | @Override 21 | public ClientDetails mapRow(ResultSet rs, int rowNum) throws SQLException { 22 | ClientDetails details = new ClientDetails(); 23 | details.clientId(rs.getString("client_id")); 24 | details.clientSecret(rs.getString("client_secret")); 25 | 26 | details.name(rs.getString("client_name")); 27 | details.clientUri(rs.getString("client_uri")); 28 | details.iconUri(rs.getString("client_icon_uri")); 29 | 30 | details.resourceIds(rs.getString("resource_ids")); 31 | details.scope(rs.getString("scope")); 32 | details.grantTypes(rs.getString("grant_types")); 33 | 34 | details.redirectUri(rs.getString("redirect_uri")); 35 | details.roles(rs.getString("roles")); 36 | details.accessTokenValidity(rs.getInt("access_token_validity")); 37 | 38 | details.refreshTokenValidity(rs.getInt("refresh_token_validity")); 39 | details.description(rs.getString("description")); 40 | details.createTime(rs.getTimestamp("create_time")); 41 | 42 | details.archived(rs.getBoolean("archived")); 43 | details.trusted(rs.getBoolean("trusted")); 44 | 45 | return details; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /resources/src/main/java/com/monkeyk/os/web/controller/OauthResourcesController.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.web.controller; 2 | 3 | import com.monkeyk.os.service.dto.UsernameDto; 4 | import org.apache.oltu.oauth2.common.OAuth; 5 | import org.apache.shiro.authz.annotation.RequiresRoles; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.stereotype.Controller; 9 | import org.springframework.web.bind.annotation.RequestMapping; 10 | import org.springframework.web.bind.annotation.ResponseBody; 11 | 12 | import javax.servlet.http.HttpServletRequest; 13 | import javax.servlet.http.HttpServletResponse; 14 | 15 | /** 16 | * Custom resource API 17 | * Protect by Oauth 18 | * 19 | * @author Shengzhao Li 20 | * @see org.apache.oltu.oauth2.rsfilter.OAuthFilter 21 | */ 22 | @Controller 23 | @RequestMapping("/rs/") 24 | public class OauthResourcesController { 25 | 26 | 27 | private static final Logger LOG = LoggerFactory.getLogger(OauthResourcesController.class); 28 | 29 | 30 | /** 31 | * RESTFUL 32 | * Return username API 33 | * 34 | * @param request HttpServletRequest 35 | * @param response HttpServletResponse 36 | * @throws Exception 37 | */ 38 | @RequiresRoles("User") 39 | @RequestMapping("username") 40 | @ResponseBody 41 | public UsernameDto username(HttpServletRequest request, HttpServletResponse response) throws Exception { 42 | 43 | final String clientId = (String) request.getAttribute(OAuth.OAUTH_CLIENT_ID); 44 | LOG.debug("Current clientId: {}", clientId); 45 | 46 | final String username = request.getUserPrincipal().getName(); 47 | LOG.debug("Current username: {}", username); 48 | 49 | return new UsernameDto(clientId, username); 50 | } 51 | 52 | 53 | } -------------------------------------------------------------------------------- /authz/src/main/webapp/WEB-INF/jsp/login.jsp: -------------------------------------------------------------------------------- 1 | <%-- 2 | * Copyright (c) 2013 Andaily Information Technology Co. Ltd 3 | * www.andaily.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * Andaily Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with Andaily Information Technology Co. Ltd. 11 | --%> 12 | <%-- 13 | * 14 | * @author Shengzhao Li 15 | --%> 16 | <%@ page contentType="text/html;charset=UTF-8" language="java" %> 17 | <%@ include file="comm-header.jsp" %> 18 | 19 | 20 | 21 | 22 | Login 23 | 24 | 25 |

Login 26 | Just test Shiro 27 |

28 | 29 |
30 | 31 | Username: (test) 32 |

33 | Password: (test) 34 |

35 | 36 |
37 | 38 |
39 |
40 |
41 |
42 |

Oauth 43 | Ignore login, testing oauth directly 44 |

45 | 46 |

47 | See oauth_test.txt 48 | firstly. 49 |

50 | 51 |

52 | oauth_test 53 |

54 |
55 | 56 | 57 | -------------------------------------------------------------------------------- /resources/src/main/java/com/monkeyk/os/web/controller/MobileResourcesController.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.web.controller; 2 | 3 | import com.monkeyk.os.infrastructure.DateUtils; 4 | import com.monkeyk.os.service.dto.SystemTimeDto; 5 | import com.monkeyk.os.web.WebUtils; 6 | import org.apache.oltu.oauth2.common.OAuth; 7 | import org.slf4j.Logger; 8 | import org.slf4j.LoggerFactory; 9 | import org.springframework.stereotype.Controller; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | import org.springframework.web.bind.annotation.ResponseBody; 12 | 13 | import javax.servlet.http.HttpServletRequest; 14 | import javax.servlet.http.HttpServletResponse; 15 | 16 | /** 17 | * Mobile resource API 18 | * Protect by Oauth 19 | *

20 | *

21 | * resource-id: mobile-resource 22 | * 23 | * @author Shengzhao Li 24 | * @see org.apache.oltu.oauth2.rsfilter.OAuthFilter 25 | */ 26 | @Controller 27 | @RequestMapping("/mobile/") 28 | public class MobileResourcesController { 29 | 30 | 31 | private static final Logger LOG = LoggerFactory.getLogger(MobileResourcesController.class); 32 | 33 | 34 | /** 35 | * Return system time API 36 | * 37 | * @param request HttpServletRequest 38 | * @param response HttpServletResponse 39 | * @throws Exception 40 | */ 41 | @RequestMapping("system_time") 42 | @ResponseBody 43 | public SystemTimeDto systemTime(HttpServletRequest request, HttpServletResponse response) throws Exception { 44 | 45 | final String clientId = (String) request.getAttribute(OAuth.OAUTH_CLIENT_ID); 46 | LOG.debug("Current clientId: {}", clientId); 47 | 48 | final String username = request.getUserPrincipal().getName(); 49 | LOG.debug("Current username: {}", username); 50 | 51 | return new SystemTimeDto(); 52 | } 53 | 54 | 55 | } -------------------------------------------------------------------------------- /authz/src/main/webapp/WEB-INF/jsp/oauth/oauth_approval.jsp: -------------------------------------------------------------------------------- 1 | <%-- 2 | * 3 | * @author Shengzhao Li 4 | --%> 5 | 6 | <%@ page contentType="text/html;charset=UTF-8" language="java" %> 7 | 8 | 9 | 10 | 11 | Oauth Approval 12 | 13 |

OAuth Approval

14 | 15 |

Do you authorize '${param.client_id}' to access your protected resources?

16 | 17 |
19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 |
41 | 42 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/domain/oauth/DefaultAuthenticationIdGenerator.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.domain.oauth; 2 | 3 | import org.apache.oltu.oauth2.common.OAuth; 4 | import org.apache.oltu.oauth2.common.utils.OAuthUtils; 5 | 6 | import java.io.UnsupportedEncodingException; 7 | import java.math.BigInteger; 8 | import java.security.MessageDigest; 9 | import java.security.NoSuchAlgorithmException; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | /** 14 | * 15-6-20 15 | * 16 | * @author Shengzhao Li 17 | */ 18 | public class DefaultAuthenticationIdGenerator implements AuthenticationIdGenerator { 19 | 20 | 21 | public DefaultAuthenticationIdGenerator() { 22 | } 23 | 24 | 25 | public String generate(String clientId, String username, String scope) { 26 | Map map = new HashMap<>(); 27 | map.put(OAuth.OAUTH_CLIENT_ID, clientId); 28 | //check it is client only 29 | if (!clientId.equals(username)) { 30 | map.put(OAuth.OAUTH_USERNAME, username); 31 | } 32 | if (!OAuthUtils.isEmpty(scope)) { 33 | map.put(OAuth.OAUTH_SCOPE, scope); 34 | } 35 | 36 | return digest(map); 37 | } 38 | 39 | 40 | protected String digest(Map map) { 41 | MessageDigest digest; 42 | try { 43 | digest = MessageDigest.getInstance("MD5"); 44 | } catch (NoSuchAlgorithmException e) { 45 | throw new IllegalStateException("MD5 algorithm not available. Fatal (should be in the JDK)."); 46 | } 47 | 48 | try { 49 | byte[] bytes = digest.digest(map.toString().getBytes("UTF-8")); 50 | return String.format("%032x", new BigInteger(1, bytes)); 51 | } catch (UnsupportedEncodingException e) { 52 | throw new IllegalStateException("UTF-8 encoding not available. Fatal (should be in the JDK)."); 53 | } 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /others/database/initial-db.ddl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | set names utf8; 5 | 6 | 7 | -- Two users: admin/admin; test/test 8 | truncate users; 9 | insert into users(id,guid,create_time,username,password,default_user) 10 | values 11 | (21,uuid(),now(),'admin','21232f297a57a5a743894a0e4a801fc3',1), 12 | (22,uuid(),now(),'test','098f6bcd4621d373cade4e832627b4f6',0); 13 | 14 | 15 | -- Two roles: User,Admin 16 | truncate roles; 17 | insert into roles(id,guid,create_time,role_name) 18 | values 19 | (21,uuid(),now(),'Admin'), 20 | (22,uuid(),now(),'User'); 21 | 22 | 23 | -- Four permissions: user:create,user:edit,user:list,user:delete 24 | truncate roles_permissions; 25 | insert into roles_permissions(roles_id, permission) 26 | values 27 | (21,'user:create'), 28 | (21,'user:edit'), 29 | (21,'user:list'), 30 | (21,'user:delete'), 31 | (22,'user:list'); 32 | 33 | 34 | -- user_roles 35 | truncate user_roles; 36 | insert into user_roles(users_id,roles_id) 37 | values 38 | (21,21), 39 | (22,22); 40 | 41 | 42 | 43 | 44 | -- Initial Oauth 45 | -- oauth_client_details 46 | truncate oauth_client_details; 47 | insert into oauth_client_details(client_id, client_secret, client_name, client_uri, 48 | client_icon_uri, resource_ids, scope, grant_types, 49 | redirect_uri, roles) 50 | values 51 | ('test','test','Test Client','http://andaily.com', 52 | 'http://andaily.com/favicon.ico','os-resource','read write','authorization_code,password,refresh_token,client_credentials', 53 | 'http://localhost:7777/spring-oauth-client/authorization_code_callback','22'); 54 | -- Mobile resource client details 55 | insert into oauth_client_details(client_id, client_secret, client_name, client_uri, 56 | client_icon_uri, resource_ids, scope, grant_types, 57 | redirect_uri, roles) 58 | values 59 | ('mobile','mobile','Mobile Client','http://andaily.com', 60 | 'http://andaily.com/favicon.ico','mobile-resource','read write','password,refresh_token', 61 | 'http://localhost:7777/spring-oauth-client/authorization_code_callback','22'); 62 | 63 | 64 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/web/context/OAuthShiroHandlerExceptionResolver.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.web.context; 2 | 3 | import com.monkeyk.os.web.WebUtils; 4 | import org.apache.oltu.oauth2.as.response.OAuthASResponse; 5 | import org.apache.oltu.oauth2.common.error.OAuthError; 6 | import org.apache.oltu.oauth2.common.exception.OAuthSystemException; 7 | import org.apache.oltu.oauth2.common.message.OAuthResponse; 8 | import org.apache.shiro.authz.AuthorizationException; 9 | import org.apache.shiro.authz.UnauthorizedException; 10 | import org.springframework.web.servlet.HandlerExceptionResolver; 11 | import org.springframework.web.servlet.ModelAndView; 12 | 13 | import javax.servlet.http.HttpServletRequest; 14 | import javax.servlet.http.HttpServletResponse; 15 | 16 | /** 17 | * 2015/9/29 18 | * 19 | * @author Shengzhao Li 20 | */ 21 | public class OAuthShiroHandlerExceptionResolver implements HandlerExceptionResolver { 22 | 23 | 24 | public OAuthShiroHandlerExceptionResolver() { 25 | } 26 | 27 | @Override 28 | public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { 29 | 30 | if (ex instanceof UnauthorizedException) { 31 | handleUnauthorizedException(response, ex); 32 | } else if (ex instanceof AuthorizationException) { 33 | handleUnauthorizedException(response, ex); 34 | } 35 | //more 36 | 37 | return null; 38 | } 39 | 40 | private void handleUnauthorizedException(HttpServletResponse response, Exception ex) { 41 | OAuthResponse oAuthResponse; 42 | try { 43 | oAuthResponse = OAuthASResponse.errorResponse(403) 44 | .setError(OAuthError.ResourceResponse.INVALID_TOKEN) 45 | .setErrorDescription(ex.getMessage()) 46 | .buildJSONMessage(); 47 | } catch (OAuthSystemException e) { 48 | throw new IllegalStateException(e); 49 | } 50 | 51 | WebUtils.writeOAuthJsonResponse(response, oAuthResponse); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /resources/src/main/java/com/monkeyk/os/web/context/OAuthShiroHandlerExceptionResolver.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.web.context; 2 | 3 | import com.monkeyk.os.web.WebUtils; 4 | import org.apache.oltu.oauth2.common.error.OAuthError; 5 | import org.apache.oltu.oauth2.common.exception.OAuthSystemException; 6 | import org.apache.oltu.oauth2.common.message.OAuthResponse; 7 | import org.apache.oltu.oauth2.rs.response.OAuthRSResponse; 8 | import org.apache.shiro.authz.AuthorizationException; 9 | import org.apache.shiro.authz.UnauthorizedException; 10 | import org.springframework.web.servlet.HandlerExceptionResolver; 11 | import org.springframework.web.servlet.ModelAndView; 12 | 13 | import javax.servlet.http.HttpServletRequest; 14 | import javax.servlet.http.HttpServletResponse; 15 | 16 | /** 17 | * 2015/9/29 18 | * 19 | * @author Shengzhao Li 20 | */ 21 | public class OAuthShiroHandlerExceptionResolver implements HandlerExceptionResolver { 22 | 23 | 24 | public OAuthShiroHandlerExceptionResolver() { 25 | } 26 | 27 | @Override 28 | public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) { 29 | 30 | if (ex instanceof UnauthorizedException) { 31 | handleUnauthorizedException(response, ex); 32 | } else if (ex instanceof AuthorizationException) { 33 | handleUnauthorizedException(response, ex); 34 | } 35 | //more 36 | 37 | return null; 38 | } 39 | 40 | private void handleUnauthorizedException(HttpServletResponse response, Exception ex) { 41 | OAuthResponse oAuthResponse; 42 | try { 43 | oAuthResponse = OAuthRSResponse.errorResponse(403) 44 | .setError(OAuthError.ResourceResponse.INVALID_TOKEN) 45 | .setErrorDescription(ex.getMessage()) 46 | .buildJSONMessage(); 47 | } catch (OAuthSystemException e) { 48 | throw new IllegalStateException(e); 49 | } 50 | 51 | WebUtils.writeOAuthJsonResponse(response, oAuthResponse); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/oauth/authorize/CodeAuthorizeHandler.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.oauth.authorize; 2 | 3 | import com.monkeyk.os.domain.oauth.ClientDetails; 4 | import com.monkeyk.os.web.WebUtils; 5 | import com.monkeyk.os.oauth.OAuthAuthxRequest; 6 | import com.monkeyk.os.oauth.validator.AbstractClientDetailsValidator; 7 | import com.monkeyk.os.oauth.validator.CodeClientDetailsValidator; 8 | import org.apache.oltu.oauth2.as.response.OAuthASResponse; 9 | import org.apache.oltu.oauth2.common.exception.OAuthSystemException; 10 | import org.apache.oltu.oauth2.common.message.OAuthResponse; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | 14 | import javax.servlet.http.HttpServletResponse; 15 | import java.io.IOException; 16 | 17 | /** 18 | * 2015/6/25 19 | *

20 | * Handle response_type = 'code' 21 | * 22 | * @author Shengzhao Li 23 | */ 24 | public class CodeAuthorizeHandler extends AbstractAuthorizeHandler { 25 | 26 | private static final Logger LOG = LoggerFactory.getLogger(CodeAuthorizeHandler.class); 27 | 28 | 29 | public CodeAuthorizeHandler(OAuthAuthxRequest oauthRequest, HttpServletResponse response) { 30 | super(oauthRequest, response); 31 | } 32 | 33 | @Override 34 | protected AbstractClientDetailsValidator getValidator() { 35 | return new CodeClientDetailsValidator(oauthRequest); 36 | } 37 | 38 | 39 | //response code 40 | @Override 41 | protected void handleResponse() throws OAuthSystemException, IOException { 42 | final ClientDetails clientDetails = clientDetails(); 43 | final String authCode = oauthService.retrieveAuthCode(clientDetails); 44 | 45 | final OAuthResponse oAuthResponse = OAuthASResponse 46 | .authorizationResponse(oauthRequest.request(), HttpServletResponse.SC_OK) 47 | .location(clientDetails.redirectUri()) 48 | .setCode(authCode) 49 | .buildQueryMessage(); 50 | LOG.debug(" 'code' response: {}", oAuthResponse); 51 | 52 | WebUtils.writeOAuthQueryResponse(response, oAuthResponse); 53 | } 54 | 55 | 56 | } 57 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/web/controller/OauthTokenController.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.web.controller; 2 | 3 | import com.monkeyk.os.web.WebUtils; 4 | import com.monkeyk.os.oauth.OAuthTokenxRequest; 5 | import com.monkeyk.os.oauth.token.OAuthTokenHandleDispatcher; 6 | import org.apache.oltu.oauth2.as.response.OAuthASResponse; 7 | import org.apache.oltu.oauth2.common.exception.OAuthProblemException; 8 | import org.apache.oltu.oauth2.common.message.OAuthResponse; 9 | import org.springframework.stereotype.Controller; 10 | import org.springframework.web.bind.annotation.RequestMapping; 11 | 12 | import javax.servlet.http.HttpServletRequest; 13 | import javax.servlet.http.HttpServletResponse; 14 | 15 | /** 16 | * 2015/7/3 17 | *

18 | * URL: oauth/token 19 | * 20 | * @author Shengzhao Li 21 | */ 22 | @Controller 23 | @RequestMapping("oauth/") 24 | public class OauthTokenController { 25 | 26 | 27 | /** 28 | * Handle grant_types as follows: 29 | *

30 | * grant_type=authorization_code 31 | * grant_type=password 32 | * grant_type=refresh_token 33 | * grant_type=client_credentials 34 | * 35 | * @param request HttpServletRequest 36 | * @param response HttpServletResponse 37 | * @throws Exception 38 | */ 39 | @RequestMapping("token") 40 | public void authorize(HttpServletRequest request, HttpServletResponse response) throws Exception { 41 | try { 42 | OAuthTokenxRequest tokenRequest = new OAuthTokenxRequest(request); 43 | 44 | OAuthTokenHandleDispatcher tokenHandleDispatcher = new OAuthTokenHandleDispatcher(tokenRequest, response); 45 | tokenHandleDispatcher.dispatch(); 46 | 47 | } catch (OAuthProblemException e) { 48 | //exception 49 | OAuthResponse oAuthResponse = OAuthASResponse 50 | .errorResponse(HttpServletResponse.SC_FOUND) 51 | .location(e.getRedirectUri()) 52 | .error(e) 53 | .buildJSONMessage(); 54 | WebUtils.writeOAuthJsonResponse(response, oAuthResponse); 55 | } 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /core/src/main/java/com/monkeyk/os/domain/users/Users.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.domain.users; 13 | 14 | import com.monkeyk.os.domain.AbstractDomain; 15 | import com.monkeyk.os.domain.AbstractIdDomain; 16 | import com.monkeyk.os.domain.shared.GuidGenerator; 17 | 18 | import java.util.Date; 19 | 20 | /** 21 | * 2015/10/26 22 | *

23 | * Table: users 24 | * 25 | * @author Shengzhao Li 26 | */ 27 | public class Users extends AbstractIdDomain { 28 | 29 | 30 | private static final long serialVersionUID = -3990278799194556012L; 31 | 32 | 33 | //unique 34 | private String username; 35 | 36 | private String password; 37 | 38 | /** 39 | * Label default user or not 40 | */ 41 | private boolean defaultUser = false; 42 | 43 | 44 | private Date lastLoginTime; 45 | 46 | 47 | public Users() { 48 | } 49 | 50 | public String username() { 51 | return username; 52 | } 53 | 54 | public Users username(String username) { 55 | this.username = username; 56 | return this; 57 | } 58 | 59 | public String password() { 60 | return password; 61 | } 62 | 63 | public Users password(String password) { 64 | this.password = password; 65 | return this; 66 | } 67 | 68 | public boolean defaultUser() { 69 | return defaultUser; 70 | } 71 | 72 | public Users defaultUser(boolean defaultUser) { 73 | this.defaultUser = defaultUser; 74 | return this; 75 | } 76 | 77 | public Date lastLoginTime() { 78 | return lastLoginTime; 79 | } 80 | 81 | public Users lastLoginTime(Date lastLoginTime) { 82 | this.lastLoginTime = lastLoginTime; 83 | return this; 84 | } 85 | 86 | 87 | } 88 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/service/business/AbstractAccessTokenHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.service.business; 13 | 14 | import com.monkeyk.os.domain.oauth.AccessToken; 15 | import com.monkeyk.os.domain.oauth.AuthenticationIdGenerator; 16 | import com.monkeyk.os.domain.oauth.ClientDetails; 17 | import com.monkeyk.os.domain.shared.BeanProvider; 18 | import org.apache.oltu.oauth2.common.exception.OAuthSystemException; 19 | import org.slf4j.Logger; 20 | import org.slf4j.LoggerFactory; 21 | import org.springframework.util.Assert; 22 | 23 | /** 24 | * 2015/10/22 25 | * 26 | * @author Shengzhao Li 27 | */ 28 | public abstract class AbstractAccessTokenHandler extends AbstractOAuthHolder { 29 | 30 | private static final Logger LOG = LoggerFactory.getLogger(AbstractAccessTokenHandler.class); 31 | 32 | 33 | protected transient AuthenticationIdGenerator authenticationIdGenerator = BeanProvider.getBean(AuthenticationIdGenerator.class); 34 | 35 | 36 | protected AccessToken createAndSaveAccessToken(ClientDetails clientDetails, boolean includeRefreshToken, String username, String authenticationId) throws OAuthSystemException { 37 | Assert.notNull(username, "username is null"); 38 | AccessToken accessToken = new AccessToken() 39 | .clientId(clientDetails.clientId()) 40 | .username(username) 41 | .tokenId(oAuthIssuer.accessToken()) 42 | .authenticationId(authenticationId) 43 | .updateByClientDetails(clientDetails); 44 | 45 | if (includeRefreshToken) { 46 | accessToken.refreshToken(oAuthIssuer.refreshToken()); 47 | } 48 | 49 | this.oauthRepository.saveAccessToken(accessToken); 50 | LOG.debug("Save AccessToken: {}", accessToken); 51 | return accessToken; 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #oauth2-shiro-redis 2 | 3 |

4 | Integrate oauth2-shiro with Redis 5 |

6 |

7 | GitHub地址: https://github.com/monkeyk/oauth2-shiro 8 |

9 | 10 | 11 |
12 |

说明

13 |

该项目具有 oauth2-shiro 的所有功能, 并添加了对 Redis 的支持

14 |

从 oauth2-shiro fork 的版本: 0.1-rc

15 |

项目使用的 Redis 版本信息 16 |
17 | spring-data-redis -> 1.5.2.RELEASE 18 |
19 | jedis -> 2.7.3 20 |

21 | 22 |
23 | 24 | 25 |
26 |

功能变化

27 |

相比 oauth2-shiro 项目, 添加并支持更多的功能与配置

28 |
    29 |
  1. 支持Redis连接属性更多的设置, 详见配置文件 resources.properties, authz.properties

  2. 30 |
  3. 提供对 ClientDetails 的操作支持, 详见 ClientDetailsService.java

  4. 31 |
  5. 重构 ClientDetails, 使其支持 序列化(Serializable)

  6. 32 |
  7. 添加配置属性 remove.token.expired, 支持当检测到 access_token 过期时删除对应的 AccessToken 数据

  8. 33 |
  9. 根据需要可去掉MYSQL数据库支持, 只使用Redis, 详见 branch: redis

  10. 34 |
  11. 重构 OAUTH2 业务实现的代码, 使结构,代码更清晰, 可读更强

  12. 35 |
36 |
37 | 38 | 39 |
40 |

使用注意

41 |

authz 与 resources 模块中配置的 Redis 必须是同一个Redis的连接信息, 方可正常工作

42 |

在项目中,使用Redis做缓存, 提高性能,同时也将数据存入MYSQL数据库; 也支持去掉MYSQL,只使用Redis(需要修改配置实现)

43 | 44 |
45 | 46 | 47 |
48 |

Project Logs

49 |

记录项目的变化与发展历程

50 | 51 |
    52 |
  1. 2015-10-21 从oauth2-shiro fork源代码到本项目中

  2. 53 |
  3. 2015-10-27 创建branch: redis, 只支持Redis操作

  4. 54 |
  5. 2016-07-08 oauth2-shiro-redis 开源

  6. 55 |
  7. 2017-01-21     加入GitHub https://github.com/monkeyk/oauth2-shiro-redis

  8. 56 |
57 |
58 | 59 | 60 |
61 |

技术支持联系方式

62 |

Email: sz@monkeyk.com

63 |
64 |

65 | 66 |

67 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/service/OauthService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Andaily Information Technology Co. Ltd 3 | * www.andaily.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * Andaily Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with Andaily Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.service; 13 | 14 | import com.monkeyk.os.domain.oauth.AccessToken; 15 | import com.monkeyk.os.domain.oauth.ClientDetails; 16 | import com.monkeyk.os.domain.oauth.OauthCode; 17 | import org.apache.oltu.oauth2.common.exception.OAuthSystemException; 18 | 19 | import java.util.Set; 20 | 21 | /** 22 | * 15-6-10 23 | * 24 | * @author Shengzhao Li 25 | */ 26 | public interface OauthService { 27 | 28 | ClientDetails loadClientDetails(String clientId); 29 | 30 | String retrieveAuthCode(ClientDetails clientDetails) throws OAuthSystemException; 31 | 32 | AccessToken retrieveAccessToken(ClientDetails clientDetails, Set scopes, boolean includeRefreshToken) throws OAuthSystemException; 33 | 34 | //Always return new AccessToken, exclude refreshToken 35 | AccessToken retrieveNewAccessToken(ClientDetails clientDetails, Set scopes) throws OAuthSystemException; 36 | 37 | OauthCode loadOauthCode(String code, ClientDetails clientDetails); 38 | 39 | boolean removeOauthCode(String code, ClientDetails clientDetails); 40 | 41 | //Always return new AccessToken 42 | AccessToken retrieveAuthorizationCodeAccessToken(ClientDetails clientDetails, String code) throws OAuthSystemException; 43 | 44 | //grant_type=password AccessToken 45 | AccessToken retrievePasswordAccessToken(ClientDetails clientDetails, Set scopes, String username) throws OAuthSystemException; 46 | 47 | //grant_type=client_credentials 48 | AccessToken retrieveClientCredentialsAccessToken(ClientDetails clientDetails, Set scopes) throws OAuthSystemException; 49 | 50 | AccessToken loadAccessTokenByRefreshToken(String refreshToken, String clientId); 51 | 52 | AccessToken changeAccessTokenByRefreshToken(String refreshToken, String clientId) throws OAuthSystemException; 53 | } 54 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/service/business/AccessTokenRetriever.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.service.business; 13 | 14 | import com.monkeyk.os.domain.oauth.AccessToken; 15 | import com.monkeyk.os.domain.oauth.ClientDetails; 16 | import org.apache.oltu.oauth2.common.exception.OAuthSystemException; 17 | import org.apache.oltu.oauth2.common.utils.OAuthUtils; 18 | import org.slf4j.Logger; 19 | import org.slf4j.LoggerFactory; 20 | 21 | import java.util.Set; 22 | 23 | /** 24 | * 2015/10/22 25 | * 26 | * @author Shengzhao Li 27 | */ 28 | public class AccessTokenRetriever extends AbstractAccessTokenHandler { 29 | 30 | private static final Logger LOG = LoggerFactory.getLogger(AccessTokenRetriever.class); 31 | 32 | private final ClientDetails clientDetails; 33 | private final Set scopes; 34 | private final boolean includeRefreshToken; 35 | 36 | public AccessTokenRetriever(ClientDetails clientDetails, Set scopes, boolean includeRefreshToken) { 37 | this.clientDetails = clientDetails; 38 | this.scopes = scopes; 39 | this.includeRefreshToken = includeRefreshToken; 40 | } 41 | 42 | public AccessToken retrieve() throws OAuthSystemException { 43 | 44 | String scope = OAuthUtils.encodeScopes(scopes); 45 | final String username = currentUsername(); 46 | final String clientId = clientDetails.clientId(); 47 | 48 | final String authenticationId = authenticationIdGenerator.generate(clientId, username, scope); 49 | 50 | AccessToken accessToken = oauthRepository.findAccessToken(clientId, username, authenticationId); 51 | if (accessToken == null) { 52 | accessToken = createAndSaveAccessToken(clientDetails, includeRefreshToken, username, authenticationId); 53 | LOG.debug("Create a new AccessToken: {}", accessToken); 54 | } 55 | 56 | return accessToken; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/infrastructure/jdbc/UsersJdbcRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.infrastructure.jdbc; 13 | 14 | import com.monkeyk.os.domain.users.*; 15 | import org.springframework.stereotype.Repository; 16 | 17 | import java.util.List; 18 | 19 | /** 20 | * 2015/10/26 21 | * 22 | * @author Shengzhao Li 23 | */ 24 | @Repository("usersJdbcRepository") 25 | public class UsersJdbcRepository extends AbstractJdbcRepository implements UsersRepository { 26 | 27 | 28 | private static UsersRowMapper usersRowMapper = new UsersRowMapper(); 29 | 30 | private static RolesRowMapper rolesRowMapper = new RolesRowMapper(); 31 | 32 | private RolesPermissionsRowMapper rolesPermissionsRowMapper = new RolesPermissionsRowMapper(); 33 | 34 | 35 | @Override 36 | public Users findUsersByUsername(String username) { 37 | final String sql = " select u.* from users u where u.archived = false and u.username = ? "; 38 | final List usersList = jdbcTemplate.query(sql, usersRowMapper, username); 39 | return usersList.isEmpty() ? null : usersList.get(0); 40 | } 41 | 42 | 43 | @Override 44 | public List findRolesByUsername(String username) { 45 | final String roleSql = " select r.* from roles r, user_roles ur, users u where u.archived = false " + 46 | " and u.id = ur.users_id and ur.roles_id = r.id and u.username = ? "; 47 | final List rolesList = jdbcTemplate.query(roleSql, rolesRowMapper, username); 48 | 49 | //load permissions 50 | for (Roles roles : rolesList) { 51 | loadRolesPermissions(roles); 52 | } 53 | 54 | return rolesList; 55 | } 56 | 57 | private void loadRolesPermissions(Roles roles) { 58 | final String pSql = " select p.* from roles_permissions p where p.roles_id = ? "; 59 | final List list = jdbcTemplate.query(pSql, rolesPermissionsRowMapper, roles.id()); 60 | roles.permissions().addAll(list); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /core/src/main/java/com/monkeyk/os/domain/AbstractIdDomain.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.domain; 13 | 14 | import com.monkeyk.os.domain.shared.GuidGenerator; 15 | 16 | /** 17 | * 2015/10/26 18 | *

19 | *

20 | * Add id, version field and so on 21 | * 扩展 AbstractDomain 的抽象类, 增加 字段id, version, archived, guid 22 | * 23 | * @author Shengzhao Li 24 | */ 25 | public abstract class AbstractIdDomain extends AbstractDomain { 26 | 27 | private static final long serialVersionUID = 4653514788456221527L; 28 | 29 | 30 | protected int id; 31 | 32 | /* 33 | * 实现数据 乐观锁 34 | * */ 35 | // Optimistic lock 36 | protected int version = 0; 37 | 38 | /** 39 | * 数据逻辑删除的 标记 40 | */ 41 | // logic delete label 42 | protected boolean archived = false; 43 | 44 | /** 45 | * 数据业务ID 46 | */ 47 | // business id 48 | protected String guid = GuidGenerator.generate(); 49 | 50 | 51 | public AbstractIdDomain() { 52 | } 53 | 54 | public int id() { 55 | return id; 56 | } 57 | 58 | @SuppressWarnings("unchecked") 59 | public T id(int id) { 60 | this.id = id; 61 | return (T) this; 62 | } 63 | 64 | public int version() { 65 | return version; 66 | } 67 | 68 | @SuppressWarnings("unchecked") 69 | public T version(int version) { 70 | this.version = version; 71 | return (T) this; 72 | } 73 | 74 | public boolean archived() { 75 | return archived; 76 | } 77 | 78 | @SuppressWarnings("unchecked") 79 | public T archived(boolean archived) { 80 | this.archived = archived; 81 | return (T) this; 82 | } 83 | 84 | public String guid() { 85 | return guid; 86 | } 87 | 88 | @SuppressWarnings("unchecked") 89 | public T guid(String guid) { 90 | this.guid = guid; 91 | return (T) this; 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/service/business/AuthCodeRetriever.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.service.business; 13 | 14 | import com.monkeyk.os.domain.oauth.ClientDetails; 15 | import com.monkeyk.os.domain.oauth.OauthCode; 16 | import org.apache.oltu.oauth2.common.exception.OAuthSystemException; 17 | import org.slf4j.Logger; 18 | import org.slf4j.LoggerFactory; 19 | 20 | /** 21 | * 2015/10/22 22 | * 23 | * @author Shengzhao Li 24 | */ 25 | public class AuthCodeRetriever extends AbstractOAuthHolder { 26 | 27 | private static final Logger LOG = LoggerFactory.getLogger(AuthCodeRetriever.class); 28 | 29 | 30 | 31 | private ClientDetails clientDetails; 32 | 33 | public AuthCodeRetriever(ClientDetails clientDetails) { 34 | this.clientDetails = clientDetails; 35 | } 36 | 37 | public String retrieve() throws OAuthSystemException { 38 | 39 | final String clientId = clientDetails.clientId(); 40 | final String username = currentUsername(); 41 | 42 | OauthCode oauthCode = oauthRepository.findOauthCodeByUsernameClientId(username, clientId); 43 | if (oauthCode != null) { 44 | //Always delete exist 45 | LOG.debug("OauthCode ({}) is existed, remove it and create a new one", oauthCode); 46 | oauthRepository.deleteOauthCode(oauthCode); 47 | } 48 | //create a new one 49 | oauthCode = createOauthCode(); 50 | 51 | return oauthCode.code(); 52 | } 53 | 54 | 55 | private OauthCode createOauthCode() throws OAuthSystemException { 56 | final String authCode = oAuthIssuer.authorizationCode(); 57 | 58 | LOG.debug("Save OauthCode authorizationCode '{}' of ClientDetails '{}'", authCode, clientDetails); 59 | final String username = currentUsername(); 60 | OauthCode oauthCode = new OauthCode().code(authCode).username(username).clientId(clientDetails.clientId()); 61 | 62 | oauthRepository.saveOauthCode(oauthCode); 63 | return oauthCode; 64 | } 65 | 66 | 67 | } 68 | -------------------------------------------------------------------------------- /resources/src/main/webapp/WEB-INF/mkk-servlet.xml: -------------------------------------------------------------------------------- 1 | 2 | 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 | 41 | 42 | 43 | 45 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /authz/src/main/resources/spring/authz-redis.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /resources/src/main/resources/spring/rs-redis.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/web/controller/ShiroController.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.web.controller; 2 | 3 | import com.monkeyk.os.service.dto.LoginDto; 4 | import org.apache.shiro.SecurityUtils; 5 | import org.apache.shiro.authc.UsernamePasswordToken; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | import org.springframework.stereotype.Controller; 9 | import org.springframework.ui.Model; 10 | import org.springframework.validation.BindingResult; 11 | import org.springframework.web.bind.annotation.ModelAttribute; 12 | import org.springframework.web.bind.annotation.RequestMapping; 13 | import org.springframework.web.bind.annotation.RequestMethod; 14 | 15 | /** 16 | * 15-6-10 17 | *

18 | * Just test Shiro 19 | * 20 | * @author Shengzhao Li 21 | */ 22 | @Controller 23 | public class ShiroController { 24 | 25 | private static final Logger LOG = LoggerFactory.getLogger(ShiroController.class); 26 | 27 | 28 | @RequestMapping("index") 29 | public String index() { 30 | return "index"; 31 | } 32 | 33 | @RequestMapping("unauthorized") 34 | public String unauthorized() { 35 | return "unauthorized"; 36 | } 37 | 38 | /* 39 | * Logout 40 | */ 41 | // @RequestMapping("logout") 42 | // public String logout() { 43 | // final Subject subject = SecurityUtils.getSubject(); 44 | // LOG.debug("{} is logout", subject.getPrincipal()); 45 | // subject.logout(); 46 | // return "redirect:/"; 47 | // } 48 | 49 | /* 50 | * Go login page 51 | */ 52 | @RequestMapping(value = "login", method = RequestMethod.GET) 53 | public String login(Model model) { 54 | final LoginDto loginDto = new LoginDto(); 55 | //TODO: Just testing 56 | loginDto.setUsername("test"); 57 | 58 | model.addAttribute("formDto", loginDto); 59 | return "login"; 60 | } 61 | 62 | @RequestMapping(value = "login", method = RequestMethod.POST) 63 | public String login(@ModelAttribute("formDto") LoginDto formDto, BindingResult errors) { 64 | 65 | UsernamePasswordToken token = formDto.token(); 66 | token.setRememberMe(false); 67 | 68 | try { 69 | SecurityUtils.getSubject().login(token); 70 | } catch (Exception e) { 71 | LOG.debug("Error authenticating.", e); 72 | errors.rejectValue("username", null, "The username or password was not correct."); 73 | return "login"; 74 | } 75 | 76 | return "redirect:index"; 77 | } 78 | 79 | 80 | } 81 | -------------------------------------------------------------------------------- /authz/src/main/webapp/WEB-INF/mkk-servlet.xml: -------------------------------------------------------------------------------- 1 | 2 | 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 | 42 | 43 | 44 | 46 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /others/oauth_test.txt: -------------------------------------------------------------------------------- 1 | 2 | Make sure project modules context path as below: 3 | authz -> authz 4 | resources -> rs 5 | 6 | 7 | -- Test grant_type = 'authorization_code' , get code 8 | 9 | http://localhost:8080/authz/oauth/authorize?response_type=code&scope=read write&client_id=test&redirect_uri=http%3A%2F%2Flocalhost%3A7777%2Fspring-oauth-client%2Fauthorization_code_callback&state=09876999 10 | 11 | http://localhost:8080/authz/oauth/authorize?response_type=code&scope=read%20write&client_id=test&redirect_uri=http%3A%2F%2Flocalhost%3A7777%2Fspring-oauth-client%2Fauthorization_code_callback&state=swss58522555 12 | 13 | 14 | -- Test grant_type = 'token' 15 | -- implicit 16 | 17 | http://localhost:8080/authz/oauth/authorize?response_type=token&scope=read write&client_id=test&client_secret=test&redirect_uri=http%3A%2F%2Flocalhost%3A7777%2Fspring-oauth-client%2Fauthorization_code_callback 18 | 19 | 20 | -- Test from 'code' get 'token' [POST] 21 | http://localhost:8080/authz/oauth/token?client_id=test&client_secret=test&grant_type=authorization_code&code=ac0bd18863b07adfb518cc6e6dfcfcab&redirect_uri=http://localhost:8080/os/oauth/authorize?response_type=code&scope=read%20write&client_id=test&redirect_uri=http%3A%2F%2Flocalhost%3A7777%2Fspring-oauth-client%2Fauthorization_code_callback&state=09876999 22 | 23 | 24 | 25 | -- Test grant_type='password' [POST] 26 | http://localhost:8080/authz/oauth/token?client_id=test&client_secret=test&grant_type=password&scope=read write&username=test&password=test 27 | 28 | 29 | 30 | -- Test grant_type='client_credentials' [POST] 31 | http://localhost:8080/authz/oauth/token?client_id=test&client_secret=test&grant_type=client_credentials&scope=read 32 | 33 | 34 | -- Test grant_type='refresh_token' [POST] 35 | http://localhost:8080/authz/oauth/token?client_id=test&client_secret=test&grant_type=refresh_token&refresh_token=b36f4978a1724aa8af8960f58abe3ba1 36 | 37 | 38 | 39 | -- 40 | Test-Page URL: http://localhost:8080/authz/resources/oauth_test.html 41 | -- 42 | 43 | 44 | --注意: scope是用空格分隔的, 如:read write 45 | 46 | 47 | 48 | -- Test resource 49 | http://localhost:8080/rs/rs/username?access_token=6b7b0726e603cd04c797d5b28c7be4c4 50 | 51 | 52 | -- 53 | -- Mobile Resource 54 | -- 55 | 56 | -- Test grant_type='password' [POST] 57 | http://localhost:8080/authz/oauth/token?client_id=mobile&client_secret=mobile&grant_type=password&scope=read write&username=test&password=test 58 | 59 | 60 | 61 | -- Test mobile resource 62 | http://qc8.cc:8080/rs/mobile/system_time?access_token=b69c2f61212780c901e69cebd6854667 63 | 64 | 65 | -------------------------------------------------------------------------------- /core/src/main/java/com/monkeyk/os/infrastructure/cache/AbstractCacheSupport.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.infrastructure.cache; 13 | 14 | import org.slf4j.Logger; 15 | import org.slf4j.LoggerFactory; 16 | import org.springframework.cache.Cache; 17 | 18 | /** 19 | * 2015/10/26 20 | *

21 | * 公共类,将常用 的缓存操作放置于此 22 | * 23 | * @author Shengzhao Li 24 | */ 25 | public abstract class AbstractCacheSupport { 26 | 27 | 28 | private static final Logger LOG = LoggerFactory.getLogger(AbstractCacheSupport.class); 29 | 30 | 31 | /** 32 | * 从指定的缓存中获取缓存数据 33 | * 34 | * @param cache Cache 35 | * @param key Cache key 36 | * @return Cache value 37 | */ 38 | protected Object getFromCache(Cache cache, String key) { 39 | final Cache.ValueWrapper valueWrapper = cache.get(key); 40 | return valueWrapper == null ? null : valueWrapper.get(); 41 | } 42 | 43 | 44 | /** 45 | * 向缓存中添加 缓存数据 46 | * 47 | * @param cache Cache 48 | * @param key Cache key 49 | * @param value Cache value, null will return false 50 | * @return True is successful,otherwise false 51 | */ 52 | protected boolean putToCache(Cache cache, Object key, Object value) { 53 | if (value == null) { 54 | LOG.debug("Ignore put to cache[{}], key = {}, because value is null", cache, key); 55 | return false; 56 | } 57 | cache.put(key, value); 58 | LOG.debug("Put [{} = {}] to cache[{}]", key, value, cache); 59 | return true; 60 | } 61 | 62 | 63 | /** 64 | * 清除缓存中具体的 缓存数据 65 | * 66 | * @param cache Cache 67 | * @param key Cache key 68 | * @return True is evict successful 69 | */ 70 | protected boolean evictFromCache(Cache cache, Object key) { 71 | if (key == null) { 72 | LOG.debug("Ignore evict from cache[{}], because key is null", cache); 73 | return false; 74 | } 75 | cache.evict(key); 76 | LOG.debug("Evict key[{}] from cache[{}]", key, cache); 77 | return true; 78 | } 79 | 80 | 81 | } 82 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/oauth/token/OAuthTokenHandleDispatcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Andaily Information Technology Co. Ltd 3 | * www.andaily.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * Andaily Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with Andaily Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.oauth.token; 13 | 14 | import com.monkeyk.os.oauth.OAuthTokenxRequest; 15 | import org.apache.oltu.oauth2.common.exception.OAuthProblemException; 16 | import org.apache.oltu.oauth2.common.exception.OAuthSystemException; 17 | import org.slf4j.Logger; 18 | import org.slf4j.LoggerFactory; 19 | 20 | import javax.servlet.http.HttpServletResponse; 21 | import java.util.ArrayList; 22 | import java.util.List; 23 | 24 | /** 25 | * 2015/7/3 26 | * 27 | * @author Shengzhao Li 28 | */ 29 | public class OAuthTokenHandleDispatcher { 30 | 31 | private static final Logger LOG = LoggerFactory.getLogger(OAuthTokenHandleDispatcher.class); 32 | 33 | private List handlers = new ArrayList<>(); 34 | 35 | private final OAuthTokenxRequest tokenRequest; 36 | private final HttpServletResponse response; 37 | 38 | public OAuthTokenHandleDispatcher(OAuthTokenxRequest tokenRequest, HttpServletResponse response) { 39 | this.tokenRequest = tokenRequest; 40 | this.response = response; 41 | 42 | initialHandlers(); 43 | } 44 | 45 | private void initialHandlers() { 46 | handlers.add(new AuthorizationCodeTokenHandler()); 47 | handlers.add(new PasswordTokenHandler()); 48 | handlers.add(new RefreshTokenHandler()); 49 | 50 | handlers.add(new ClientCredentialsTokenHandler()); 51 | 52 | LOG.debug("Initialed '{}' OAuthTokenHandler(s): {}", handlers.size(), handlers); 53 | } 54 | 55 | 56 | public void dispatch() throws OAuthProblemException, OAuthSystemException { 57 | for (OAuthTokenHandler handler : handlers) { 58 | if (handler.support(tokenRequest)) { 59 | LOG.debug("Found '{}' handle OAuthTokenxRequest: {}", handler, tokenRequest); 60 | handler.handle(tokenRequest, response); 61 | return; 62 | } 63 | } 64 | throw new IllegalStateException("Not found 'OAuthTokenHandler' to handle OAuthTokenxRequest: " + tokenRequest); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /authz/src/main/webapp/WEB-INF/jsp/oauth/oauth_login.jsp: -------------------------------------------------------------------------------- 1 | <%-- 2 | * Copyright (c) 2013 Andaily Information Technology Co. Ltd 3 | * www.andaily.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * Andaily Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with Andaily Information Technology Co. Ltd. 11 | --%> 12 | <%-- 13 | * 14 | * @author Shengzhao Li 15 | --%> 16 | <%@ page contentType="text/html;charset=UTF-8" language="java" %> 17 | <%@ include file="../comm-header.jsp" %> 18 | 19 | 20 | 21 | Oauth Login 22 | 23 | 24 | 25 |

26 |

Oauth Login

27 | 28 |

29 | Login for client_id: '${param.client_id}'. 30 |

31 | 32 |
33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | Username: 41 |

42 | Password: 43 |

44 | 45 |
46 | Login failed 47 |
48 |
49 | 50 |
51 |

You can use the users to login as follow:

52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 |
usernamepasswordgrant_typesroles
testtestauthorization_code,password,refresh_token,client_credentialsUser(id=22)
70 |
71 | 72 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/service/business/AuthorizationCodeAccessTokenRetriever.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.service.business; 13 | 14 | import com.monkeyk.os.domain.oauth.AccessToken; 15 | import com.monkeyk.os.domain.oauth.ClientDetails; 16 | import com.monkeyk.os.domain.oauth.OauthCode; 17 | import org.apache.oltu.oauth2.common.exception.OAuthSystemException; 18 | import org.slf4j.Logger; 19 | import org.slf4j.LoggerFactory; 20 | 21 | /** 22 | * 2015/10/26 23 | * 24 | * @author Shengzhao Li 25 | */ 26 | public class AuthorizationCodeAccessTokenRetriever extends AbstractAccessTokenHandler { 27 | 28 | 29 | private static final Logger LOG = LoggerFactory.getLogger(AuthorizationCodeAccessTokenRetriever.class); 30 | 31 | 32 | private ClientDetails clientDetails; 33 | private String code; 34 | 35 | public AuthorizationCodeAccessTokenRetriever(ClientDetails clientDetails, String code) { 36 | this.clientDetails = clientDetails; 37 | this.code = code; 38 | } 39 | 40 | 41 | //Always return new AccessToken 42 | public AccessToken retrieve() throws OAuthSystemException { 43 | 44 | final OauthCode oauthCode = loadOauthCode(); 45 | final String username = oauthCode.username(); 46 | 47 | final String clientId = clientDetails.clientId(); 48 | final String authenticationId = authenticationIdGenerator.generate(clientId, username, null); 49 | 50 | AccessToken accessToken = oauthRepository.findAccessToken(clientId, username, authenticationId); 51 | if (accessToken != null) { 52 | LOG.debug("Delete existed AccessToken: {}", accessToken); 53 | oauthRepository.deleteAccessToken(accessToken); 54 | } 55 | accessToken = createAndSaveAccessToken(clientDetails, clientDetails.supportRefreshToken(), username, authenticationId); 56 | LOG.debug("Create a new AccessToken: {}", accessToken); 57 | 58 | return accessToken; 59 | } 60 | 61 | private OauthCode loadOauthCode() { 62 | final String clientId = clientDetails.clientId(); 63 | return oauthRepository.findOauthCode(code, clientId); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /resources/src/main/java/com/monkeyk/os/infrastructure/jdbc/UsersRSJdbcRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.infrastructure.jdbc; 13 | 14 | import com.monkeyk.os.domain.users.Roles; 15 | import com.monkeyk.os.domain.users.RolesPermissions; 16 | import com.monkeyk.os.domain.users.Users; 17 | import com.monkeyk.os.domain.users.UsersRepository; 18 | import org.springframework.stereotype.Repository; 19 | 20 | import java.util.List; 21 | 22 | /** 23 | * 2015/10/27 24 | * 25 | * @author Shengzhao Li 26 | */ 27 | @Repository("usersRSJdbcRepository") 28 | public class UsersRSJdbcRepository extends AbstractJdbcRepository implements UsersRepository { 29 | 30 | 31 | private static UsersRowMapper usersRowMapper = new UsersRowMapper(); 32 | 33 | private static RolesRowMapper rolesRowMapper = new RolesRowMapper(); 34 | 35 | private RolesPermissionsRowMapper rolesPermissionsRowMapper = new RolesPermissionsRowMapper(); 36 | 37 | 38 | @Override 39 | public Users findUsersByUsername(String username) { 40 | final String sql = " select u.* from users u where u.archived = false and u.username = ? "; 41 | final List usersList = jdbcTemplate.query(sql, usersRowMapper, username); 42 | return usersList.isEmpty() ? null : usersList.get(0); 43 | } 44 | 45 | 46 | @Override 47 | public List findRolesByUsername(String username) { 48 | final String roleSql = " select r.* from roles r, user_roles ur, users u where u.archived = false " + 49 | " and u.id = ur.users_id and ur.roles_id = r.id and u.username = ? "; 50 | final List rolesList = jdbcTemplate.query(roleSql, rolesRowMapper, username); 51 | 52 | //load permissions 53 | for (Roles roles : rolesList) { 54 | loadRolesPermissions(roles); 55 | } 56 | 57 | return rolesList; 58 | } 59 | 60 | private void loadRolesPermissions(Roles roles) { 61 | final String pSql = " select p.* from roles_permissions p where p.roles_id = ? "; 62 | final List list = jdbcTemplate.query(pSql, rolesPermissionsRowMapper, roles.id()); 63 | roles.permissions().addAll(list); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/oauth/validator/TokenClientDetailsValidator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Andaily Information Technology Co. Ltd 3 | * www.andaily.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * Andaily Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with Andaily Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.oauth.validator; 13 | 14 | import com.monkeyk.os.domain.oauth.ClientDetails; 15 | import org.apache.oltu.oauth2.as.request.OAuthAuthzRequest; 16 | import org.apache.oltu.oauth2.common.exception.OAuthSystemException; 17 | import org.apache.oltu.oauth2.common.message.OAuthResponse; 18 | import org.slf4j.Logger; 19 | import org.slf4j.LoggerFactory; 20 | 21 | import java.util.Set; 22 | 23 | /** 24 | * 15-6-13 25 | * 26 | * @author Shengzhao Li 27 | */ 28 | public class TokenClientDetailsValidator extends AbstractClientDetailsValidator { 29 | 30 | private static final Logger LOG = LoggerFactory.getLogger(TokenClientDetailsValidator.class); 31 | 32 | 33 | public TokenClientDetailsValidator(OAuthAuthzRequest oauthRequest) { 34 | super(oauthRequest); 35 | } 36 | 37 | /* 38 | * grant_type="implicit" -> response_type="token" 39 | * ?response_type=token&scope=read,write&client_id=[client_id]&client_secret=[client_secret]&redirect_uri=[redirect_uri] 40 | * */ 41 | @Override 42 | public OAuthResponse validateSelf(ClientDetails clientDetails) throws OAuthSystemException { 43 | 44 | //validate client_secret 45 | final String clientSecret = oauthRequest.getClientSecret(); 46 | if (clientSecret == null || !clientSecret.equals(clientDetails.clientSecret())) { 47 | return invalidClientSecretResponse(); 48 | } 49 | 50 | //validate redirect_uri 51 | final String redirectURI = oauthRequest.getRedirectURI(); 52 | if (redirectURI == null || !redirectURI.equals(clientDetails.redirectUri())) { 53 | LOG.debug("Invalid redirect_uri '{}' by response_type = 'code', client_id = '{}'", redirectURI, clientDetails.clientId()); 54 | return invalidRedirectUriResponse(); 55 | } 56 | 57 | //validate scope 58 | final Set scopes = oauthRequest.getScopes(); 59 | if (scopes.isEmpty() || excludeScopes(scopes, clientDetails)) { 60 | return invalidScopeResponse(); 61 | } 62 | 63 | 64 | return null; 65 | } 66 | 67 | 68 | } 69 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/oauth/validator/ClientCredentialsClientDetailsValidator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Andaily Information Technology Co. Ltd 3 | * www.andaily.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * Andaily Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with Andaily Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.oauth.validator; 13 | 14 | import com.monkeyk.os.domain.oauth.ClientDetails; 15 | import com.monkeyk.os.oauth.OAuthTokenxRequest; 16 | import org.apache.oltu.oauth2.common.exception.OAuthSystemException; 17 | import org.apache.oltu.oauth2.common.message.OAuthResponse; 18 | import org.slf4j.Logger; 19 | import org.slf4j.LoggerFactory; 20 | 21 | import java.util.Set; 22 | 23 | /** 24 | * 2015/7/5 25 | * 26 | * @author Shengzhao Li 27 | */ 28 | public class ClientCredentialsClientDetailsValidator extends AbstractOauthTokenValidator { 29 | 30 | private static final Logger LOG = LoggerFactory.getLogger(ClientCredentialsClientDetailsValidator.class); 31 | 32 | 33 | public ClientCredentialsClientDetailsValidator(OAuthTokenxRequest oauthRequest) { 34 | super(oauthRequest); 35 | } 36 | 37 | /* 38 | * /oauth/token?client_id=credentials-client&client_secret=credentials-secret&grant_type=client_credentials&scope=read write 39 | * */ 40 | @Override 41 | protected OAuthResponse validateSelf(ClientDetails clientDetails) throws OAuthSystemException { 42 | 43 | //validate grant_type 44 | final String grantType = grantType(); 45 | if (!clientDetails.grantTypes().contains(grantType)) { 46 | LOG.debug("Invalid grant_type '{}', client_id = '{}'", grantType, clientDetails.clientId()); 47 | return invalidGrantTypeResponse(grantType); 48 | } 49 | 50 | //validate client_secret 51 | final String clientSecret = oauthRequest.getClientSecret(); 52 | if (clientSecret == null || !clientSecret.equals(clientDetails.clientSecret())) { 53 | LOG.debug("Invalid client_secret '{}', client_id = '{}'", clientSecret, clientDetails.clientId()); 54 | return invalidClientSecretResponse(); 55 | } 56 | 57 | //validate scope 58 | final Set scopes = oauthRequest.getScopes(); 59 | if (scopes.isEmpty() || excludeScopes(scopes, clientDetails)) { 60 | return invalidScopeResponse(); 61 | } 62 | 63 | return null; 64 | } 65 | 66 | 67 | } 68 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/oauth/OAuthHandler.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.oauth; 2 | 3 | import com.monkeyk.os.domain.oauth.AccessToken; 4 | import com.monkeyk.os.domain.oauth.ClientDetails; 5 | import com.monkeyk.os.domain.shared.BeanProvider; 6 | import com.monkeyk.os.service.OauthService; 7 | import org.apache.commons.lang.StringUtils; 8 | import org.apache.oltu.oauth2.as.response.OAuthASResponse; 9 | import org.apache.oltu.oauth2.common.exception.OAuthSystemException; 10 | import org.apache.oltu.oauth2.common.message.OAuthResponse; 11 | import org.slf4j.Logger; 12 | import org.slf4j.LoggerFactory; 13 | 14 | import javax.servlet.http.HttpServletResponse; 15 | 16 | /** 17 | * 2015/7/3 18 | * 19 | * @author Shengzhao Li 20 | */ 21 | public abstract class OAuthHandler { 22 | 23 | 24 | private static final Logger LOG = LoggerFactory.getLogger(OAuthHandler.class); 25 | 26 | protected transient OauthService oauthService = BeanProvider.getBean(OauthService.class); 27 | 28 | 29 | private ClientDetails clientDetails; 30 | 31 | 32 | protected ClientDetails clientDetails() { 33 | if (clientDetails == null) { 34 | final String clientId = clientId(); 35 | clientDetails = oauthService.loadClientDetails(clientId); 36 | LOG.debug("Load ClientDetails: {} by clientId: {}", clientDetails, clientId); 37 | } 38 | return clientDetails; 39 | } 40 | 41 | 42 | /** 43 | * Create AccessToken response 44 | * 45 | * @param accessToken AccessToken 46 | * @param queryOrJson True is QueryMessage, false is JSON message 47 | * @return OAuthResponse 48 | * @throws org.apache.oltu.oauth2.common.exception.OAuthSystemException 49 | */ 50 | protected OAuthResponse createTokenResponse(AccessToken accessToken, boolean queryOrJson) throws OAuthSystemException { 51 | final ClientDetails clientDetails = clientDetails(); 52 | 53 | final OAuthASResponse.OAuthTokenResponseBuilder builder = OAuthASResponse 54 | .tokenResponse(HttpServletResponse.SC_OK) 55 | .location(clientDetails.redirectUri()) 56 | .setAccessToken(accessToken.tokenId()) 57 | .setExpiresIn(String.valueOf(accessToken.currentTokenExpiredSeconds())) 58 | .setTokenType(accessToken.tokenType()); 59 | 60 | final String refreshToken = accessToken.refreshToken(); 61 | if (StringUtils.isNotEmpty(refreshToken)) { 62 | builder.setRefreshToken(refreshToken); 63 | } 64 | 65 | return queryOrJson ? builder.buildQueryMessage() : builder.buildJSONMessage(); 66 | } 67 | 68 | 69 | protected abstract String clientId(); 70 | 71 | } 72 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/service/business/NewAccessTokenRetriever.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.service.business; 13 | 14 | import com.monkeyk.os.domain.oauth.AccessToken; 15 | import com.monkeyk.os.domain.oauth.ClientDetails; 16 | import org.apache.oltu.oauth2.common.exception.OAuthSystemException; 17 | import org.apache.oltu.oauth2.common.utils.OAuthUtils; 18 | import org.slf4j.Logger; 19 | import org.slf4j.LoggerFactory; 20 | 21 | import java.util.Set; 22 | 23 | /** 24 | * 2015/10/26 25 | *

26 | * Always return new AccessToken, exclude refreshToken 27 | * 28 | * @author Shengzhao Li 29 | */ 30 | public class NewAccessTokenRetriever extends AbstractAccessTokenHandler { 31 | 32 | 33 | private static final Logger LOG = LoggerFactory.getLogger(NewAccessTokenRetriever.class); 34 | 35 | 36 | private final ClientDetails clientDetails; 37 | private final Set scopes; 38 | 39 | public NewAccessTokenRetriever(ClientDetails clientDetails, Set scopes) { 40 | this.clientDetails = clientDetails; 41 | this.scopes = scopes; 42 | } 43 | 44 | //Always return new AccessToken, exclude refreshToken 45 | public AccessToken retrieve() throws OAuthSystemException { 46 | 47 | String scopeAsText = getScope(); 48 | final String username = currentUsername(); 49 | final String clientId = clientDetails.clientId(); 50 | 51 | final String authenticationId = authenticationIdGenerator.generate(clientId, username, scopeAsText); 52 | 53 | AccessToken accessToken = oauthRepository.findAccessToken(clientId, username, authenticationId); 54 | if (accessToken != null) { 55 | LOG.debug("Delete existed AccessToken: {}", accessToken); 56 | oauthRepository.deleteAccessToken(accessToken); 57 | } 58 | accessToken = createAndSaveAccessToken(clientDetails, false, username, authenticationId); 59 | LOG.debug("Create a new AccessToken: {}", accessToken); 60 | 61 | return accessToken; 62 | } 63 | 64 | private String getScope() { 65 | if (scopes != null) { 66 | return OAuthUtils.encodeScopes(scopes); 67 | } else { 68 | return null; 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/service/business/AccessTokenByRefreshTokenChanger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.service.business; 13 | 14 | import com.monkeyk.os.domain.oauth.AccessToken; 15 | import com.monkeyk.os.domain.oauth.ClientDetails; 16 | import org.apache.oltu.oauth2.common.exception.OAuthSystemException; 17 | import org.slf4j.Logger; 18 | import org.slf4j.LoggerFactory; 19 | 20 | /** 21 | * 2015/10/26 22 | * 23 | * @author Shengzhao Li 24 | */ 25 | public class AccessTokenByRefreshTokenChanger extends AbstractAccessTokenHandler { 26 | 27 | 28 | private static final Logger LOG = LoggerFactory.getLogger(AccessTokenByRefreshTokenChanger.class); 29 | 30 | 31 | private final String refreshToken; 32 | private final String clientId; 33 | 34 | public AccessTokenByRefreshTokenChanger(String refreshToken, String clientId) { 35 | this.refreshToken = refreshToken; 36 | this.clientId = clientId; 37 | } 38 | 39 | /** 40 | * Get AccessToken 41 | * Generate a new AccessToken from existed(exclude token,refresh_token) 42 | * Update access_token,refresh_token, expired. 43 | * Save and remove old 44 | */ 45 | public AccessToken change() throws OAuthSystemException { 46 | 47 | final AccessToken oldToken = oauthRepository.findAccessTokenByRefreshToken(refreshToken, clientId); 48 | 49 | AccessToken newAccessToken = oldToken.cloneMe(); 50 | LOG.debug("Create new AccessToken: {} from old AccessToken: {}", newAccessToken, oldToken); 51 | 52 | ClientDetails details = oauthRepository.findClientDetails(clientId); 53 | newAccessToken.updateByClientDetails(details); 54 | 55 | final String authId = authenticationIdGenerator.generate(clientId, oldToken.username(), null); 56 | newAccessToken.authenticationId(authId) 57 | .tokenId(oAuthIssuer.accessToken()) 58 | .refreshToken(oAuthIssuer.refreshToken()); 59 | 60 | oauthRepository.deleteAccessToken(oldToken); 61 | LOG.debug("Delete old AccessToken: {}", oldToken); 62 | 63 | oauthRepository.saveAccessToken(newAccessToken); 64 | LOG.debug("Save new AccessToken: {}", newAccessToken); 65 | 66 | return newAccessToken; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/oauth/validator/CodeClientDetailsValidator.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.oauth.validator; 2 | 3 | import com.monkeyk.os.domain.oauth.ClientDetails; 4 | import org.apache.commons.lang.StringUtils; 5 | import org.apache.oltu.oauth2.as.request.OAuthAuthzRequest; 6 | import org.apache.oltu.oauth2.common.error.OAuthError; 7 | import org.apache.oltu.oauth2.common.exception.OAuthSystemException; 8 | import org.apache.oltu.oauth2.common.message.OAuthResponse; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | import javax.servlet.http.HttpServletResponse; 13 | import java.util.Set; 14 | 15 | /** 16 | * 15-6-13 17 | * 18 | * @author Shengzhao Li 19 | */ 20 | public class CodeClientDetailsValidator extends AbstractClientDetailsValidator { 21 | 22 | private static final Logger LOG = LoggerFactory.getLogger(CodeClientDetailsValidator.class); 23 | 24 | public CodeClientDetailsValidator(OAuthAuthzRequest oauthRequest) { 25 | super(oauthRequest); 26 | } 27 | 28 | /* 29 | * grant_type="authorization_code" 30 | * ?response_type=code&scope=read,write&client_id=[client_id]&redirect_uri=[redirect_uri]&state=[state] 31 | * */ 32 | @Override 33 | public OAuthResponse validateSelf(ClientDetails clientDetails) throws OAuthSystemException { 34 | //validate redirect_uri 35 | final String redirectURI = oauthRequest.getRedirectURI(); 36 | if (redirectURI == null || !redirectURI.equals(clientDetails.redirectUri())) { 37 | LOG.debug("Invalid redirect_uri '{}' by response_type = 'code', client_id = '{}'", redirectURI, clientDetails.clientId()); 38 | return invalidRedirectUriResponse(); 39 | } 40 | 41 | //validate scope 42 | final Set scopes = oauthRequest.getScopes(); 43 | if (scopes.isEmpty() || excludeScopes(scopes, clientDetails)) { 44 | return invalidScopeResponse(); 45 | } 46 | 47 | //validate state 48 | final String state = getState(); 49 | if (StringUtils.isEmpty(state)) { 50 | LOG.debug("Invalid 'state', it is required, but it is empty"); 51 | return invalidStateResponse(); 52 | } 53 | 54 | return null; 55 | } 56 | 57 | private String getState() { 58 | return ((OAuthAuthzRequest) oauthRequest).getState(); 59 | } 60 | 61 | private OAuthResponse invalidStateResponse() throws OAuthSystemException { 62 | return OAuthResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST) 63 | .setError(OAuthError.CodeResponse.INVALID_REQUEST) 64 | .setErrorDescription("Parameter 'state' is required") 65 | .buildJSONMessage(); 66 | } 67 | 68 | 69 | } 70 | -------------------------------------------------------------------------------- /authz/src/test/java/com/monkeyk/os/web/ShiroTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Andaily Information Technology Co. Ltd 3 | * www.andaily.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * Andaily Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with Andaily Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.web; 13 | 14 | import org.apache.shiro.SecurityUtils; 15 | import org.apache.shiro.authc.UsernamePasswordToken; 16 | import org.apache.shiro.crypto.hash.Md5Hash; 17 | import org.apache.shiro.mgt.DefaultSecurityManager; 18 | import org.apache.shiro.mgt.SecurityManager; 19 | import org.apache.shiro.realm.Realm; 20 | import org.apache.shiro.realm.SimpleAccountRealm; 21 | import org.apache.shiro.subject.Subject; 22 | import org.testng.annotations.Test; 23 | 24 | import java.util.ArrayList; 25 | import java.util.List; 26 | 27 | import static org.testng.Assert.assertFalse; 28 | import static org.testng.Assert.assertTrue; 29 | 30 | /** 31 | * 15-6-10 32 | * 33 | * @author Shengzhao Li 34 | */ 35 | public class ShiroTest { 36 | 37 | 38 | @Test 39 | public void login() { 40 | String username = "abc"; 41 | //init SecurityManager 42 | SimpleAccountRealm realm = new SimpleAccountRealm("simple-realm"); 43 | realm.addAccount(username, "abc", "USER"); 44 | 45 | SimpleAccountRealm realm2 = new SimpleAccountRealm("simple-realm2"); 46 | realm2.addAccount(username, "abc", "USER", "ADMIN"); 47 | 48 | List realmList = new ArrayList<>(); 49 | realmList.add(realm); 50 | realmList.add(realm2); 51 | 52 | SecurityManager securityManager = new DefaultSecurityManager(realmList); 53 | SecurityUtils.setSecurityManager(securityManager); 54 | 55 | UsernamePasswordToken token = new UsernamePasswordToken(username, "abcdd"); 56 | 57 | final Subject subject = SecurityUtils.getSubject(); 58 | subject.login(token); 59 | 60 | 61 | final Subject subject1 = SecurityUtils.getSubject(); 62 | assertTrue(subject1.isAuthenticated()); 63 | 64 | assertFalse(subject1.isPermitted("OK")); 65 | assertTrue(subject1.hasRole("USER")); 66 | 67 | // assertTrue(subject1.isPermitted("USER:c,u")); 68 | 69 | 70 | } 71 | 72 | 73 | @Test 74 | public void md5() { 75 | 76 | Md5Hash md5Hash = new Md5Hash("admin"); 77 | System.out.println(md5Hash.toString()); 78 | System.out.println(md5Hash.toHex()); 79 | System.out.println(md5Hash.toBase64()); 80 | 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /resources/src/test/java/com/monkeyk/os/web/ShiroTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Andaily Information Technology Co. Ltd 3 | * www.andaily.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * Andaily Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with Andaily Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.web; 13 | 14 | import org.apache.shiro.SecurityUtils; 15 | import org.apache.shiro.authc.UsernamePasswordToken; 16 | import org.apache.shiro.crypto.hash.Md5Hash; 17 | import org.apache.shiro.mgt.DefaultSecurityManager; 18 | import org.apache.shiro.mgt.SecurityManager; 19 | import org.apache.shiro.realm.Realm; 20 | import org.apache.shiro.realm.SimpleAccountRealm; 21 | import org.apache.shiro.subject.Subject; 22 | import org.testng.annotations.Test; 23 | 24 | import java.util.ArrayList; 25 | import java.util.List; 26 | 27 | import static org.testng.Assert.assertFalse; 28 | import static org.testng.Assert.assertTrue; 29 | 30 | /** 31 | * 15-6-10 32 | * 33 | * @author Shengzhao Li 34 | */ 35 | public class ShiroTest { 36 | 37 | 38 | @Test 39 | public void login() { 40 | String username = "abc"; 41 | //init SecurityManager 42 | SimpleAccountRealm realm = new SimpleAccountRealm("simple-realm"); 43 | realm.addAccount(username, "abc", "USER"); 44 | 45 | SimpleAccountRealm realm2 = new SimpleAccountRealm("simple-realm2"); 46 | realm2.addAccount(username, "abc", "USER", "ADMIN"); 47 | 48 | List realmList = new ArrayList<>(); 49 | realmList.add(realm); 50 | realmList.add(realm2); 51 | 52 | SecurityManager securityManager = new DefaultSecurityManager(realmList); 53 | SecurityUtils.setSecurityManager(securityManager); 54 | 55 | UsernamePasswordToken token = new UsernamePasswordToken(username, "abcdd"); 56 | 57 | final Subject subject = SecurityUtils.getSubject(); 58 | subject.login(token); 59 | 60 | 61 | final Subject subject1 = SecurityUtils.getSubject(); 62 | assertTrue(subject1.isAuthenticated()); 63 | 64 | assertFalse(subject1.isPermitted("OK")); 65 | assertTrue(subject1.hasRole("USER")); 66 | 67 | // assertTrue(subject1.isPermitted("USER:c,u")); 68 | 69 | 70 | } 71 | 72 | 73 | @Test 74 | public void md5() { 75 | 76 | Md5Hash md5Hash = new Md5Hash("admin"); 77 | System.out.println(md5Hash.toString()); 78 | System.out.println(md5Hash.toHex()); 79 | System.out.println(md5Hash.toBase64()); 80 | 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/oauth/validator/PasswordClientDetailsValidator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Andaily Information Technology Co. Ltd 3 | * www.andaily.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * Andaily Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with Andaily Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.oauth.validator; 13 | 14 | import com.monkeyk.os.domain.oauth.ClientDetails; 15 | import com.monkeyk.os.oauth.OAuthTokenxRequest; 16 | import org.apache.oltu.oauth2.common.exception.OAuthSystemException; 17 | import org.apache.oltu.oauth2.common.message.OAuthResponse; 18 | import org.slf4j.Logger; 19 | import org.slf4j.LoggerFactory; 20 | 21 | import java.util.Set; 22 | 23 | /** 24 | * 2015/7/5 25 | * 26 | * @author Shengzhao Li 27 | */ 28 | public class PasswordClientDetailsValidator extends AbstractOauthTokenValidator { 29 | 30 | private static final Logger LOG = LoggerFactory.getLogger(PasswordClientDetailsValidator.class); 31 | 32 | 33 | public PasswordClientDetailsValidator(OAuthTokenxRequest oauthRequest) { 34 | super(oauthRequest); 35 | } 36 | 37 | /* 38 | * /oauth/token?client_id=mobile-client&client_secret=mobile&grant_type=password&scope=read,write&username=mobile&password=mobile 39 | * */ 40 | @Override 41 | protected OAuthResponse validateSelf(ClientDetails clientDetails) throws OAuthSystemException { 42 | 43 | //validate grant_type 44 | final String grantType = grantType(); 45 | if (!clientDetails.grantTypes().contains(grantType)) { 46 | LOG.debug("Invalid grant_type '{}', client_id = '{}'", grantType, clientDetails.clientId()); 47 | return invalidGrantTypeResponse(grantType); 48 | } 49 | 50 | //validate client_secret 51 | final String clientSecret = oauthRequest.getClientSecret(); 52 | if (clientSecret == null || !clientSecret.equals(clientDetails.clientSecret())) { 53 | LOG.debug("Invalid client_secret '{}', client_id = '{}'", clientSecret, clientDetails.clientId()); 54 | return invalidClientSecretResponse(); 55 | } 56 | 57 | //validate scope 58 | final Set scopes = oauthRequest.getScopes(); 59 | if (scopes.isEmpty() || excludeScopes(scopes, clientDetails)) { 60 | return invalidScopeResponse(); 61 | } 62 | 63 | //validate username,password 64 | if (invalidUsernamePassword()) { 65 | return invalidUsernamePasswordResponse(); 66 | } 67 | 68 | 69 | return null; 70 | } 71 | 72 | 73 | } 74 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/oauth/token/RefreshTokenHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Andaily Information Technology Co. Ltd 3 | * www.andaily.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * Andaily Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with Andaily Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.oauth.token; 13 | 14 | import com.monkeyk.os.domain.oauth.AccessToken; 15 | import com.monkeyk.os.oauth.OAuthTokenxRequest; 16 | import com.monkeyk.os.oauth.validator.AbstractClientDetailsValidator; 17 | import com.monkeyk.os.oauth.validator.RefreshTokenClientDetailsValidator; 18 | import com.monkeyk.os.web.WebUtils; 19 | import org.apache.oltu.oauth2.common.exception.OAuthProblemException; 20 | import org.apache.oltu.oauth2.common.exception.OAuthSystemException; 21 | import org.apache.oltu.oauth2.common.message.OAuthResponse; 22 | import org.apache.oltu.oauth2.common.message.types.GrantType; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | 26 | /** 27 | * 2015/7/3 28 | *

29 | * grant_type=refresh_token 30 | * 31 | * @author Shengzhao Li 32 | */ 33 | public class RefreshTokenHandler extends AbstractOAuthTokenHandler { 34 | 35 | private static final Logger LOG = LoggerFactory.getLogger(RefreshTokenHandler.class); 36 | 37 | 38 | @Override 39 | public boolean support(OAuthTokenxRequest tokenRequest) throws OAuthProblemException { 40 | final String grantType = tokenRequest.getGrantType(); 41 | return GrantType.REFRESH_TOKEN.toString().equalsIgnoreCase(grantType); 42 | } 43 | 44 | /** 45 | * URL demo: 46 | * /oauth/token?client_id=mobile-client&client_secret=mobile&grant_type=refresh_token&refresh_token=b36f4978-a172-4aa8-af89-60f58abe3ba1 47 | * 48 | * @throws org.apache.oltu.oauth2.common.exception.OAuthProblemException 49 | */ 50 | @Override 51 | public void handleAfterValidation() throws OAuthProblemException, OAuthSystemException { 52 | 53 | final String refreshToken = tokenRequest.getRefreshToken(); 54 | AccessToken accessToken = oauthService.changeAccessTokenByRefreshToken(refreshToken, tokenRequest.getClientId()); 55 | 56 | final OAuthResponse tokenResponse = createTokenResponse(accessToken, false); 57 | 58 | LOG.debug("'refresh_token' response: {}", tokenResponse); 59 | WebUtils.writeOAuthJsonResponse(response, tokenResponse); 60 | 61 | } 62 | 63 | @Override 64 | protected AbstractClientDetailsValidator getValidator() { 65 | return new RefreshTokenClientDetailsValidator(tokenRequest); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /authz/src/main/resources/spring/authz-security.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 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 | /favicon.ico = anon 46 | /resources/** = anon 47 | /login = anon 48 | /unauthorized = anon 49 | # OAuth anon 50 | /oauth/** = anon 51 | /logout = logout 52 | # admin role 53 | /admin/** = authc, roles["Admin"] 54 | #user permissions 55 | /user/list = authc, perms["user:list"] 56 | /user/create = authc, perms["user:create"] 57 | # everything else requires authentication: 58 | /** = authc 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/oauth/validator/AbstractOauthTokenValidator.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Andaily Information Technology Co. Ltd 3 | * www.andaily.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * Andaily Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with Andaily Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.oauth.validator; 13 | 14 | import com.monkeyk.os.oauth.OAuthTokenxRequest; 15 | import org.apache.oltu.oauth2.common.error.OAuthError; 16 | import org.apache.oltu.oauth2.common.exception.OAuthSystemException; 17 | import org.apache.oltu.oauth2.common.message.OAuthResponse; 18 | import org.apache.shiro.SecurityUtils; 19 | import org.apache.shiro.authc.UsernamePasswordToken; 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | 23 | import javax.servlet.http.HttpServletResponse; 24 | 25 | /** 26 | * 2015/7/4 27 | * 28 | * @author Shengzhao Li 29 | */ 30 | public abstract class AbstractOauthTokenValidator extends AbstractClientDetailsValidator { 31 | 32 | private static final Logger LOG = LoggerFactory.getLogger(AbstractOauthTokenValidator.class); 33 | 34 | 35 | protected OAuthTokenxRequest tokenRequest; 36 | 37 | protected AbstractOauthTokenValidator(OAuthTokenxRequest tokenRequest) { 38 | super(tokenRequest); 39 | this.tokenRequest = tokenRequest; 40 | } 41 | 42 | 43 | protected String grantType() { 44 | return tokenRequest.getGrantType(); 45 | } 46 | 47 | 48 | protected OAuthResponse invalidGrantTypeResponse(String grantType) throws OAuthSystemException { 49 | return OAuthResponse.errorResponse(HttpServletResponse.SC_UNAUTHORIZED) 50 | .setError(OAuthError.TokenResponse.INVALID_GRANT) 51 | .setErrorDescription("Invalid grant_type '" + grantType + "'") 52 | .buildJSONMessage(); 53 | } 54 | 55 | 56 | //true is invalided 57 | protected boolean invalidUsernamePassword() { 58 | final String username = tokenRequest.getUsername(); 59 | final String password = tokenRequest.getPassword(); 60 | try { 61 | SecurityUtils.getSubject().login(new UsernamePasswordToken(username, password)); 62 | } catch (Exception e) { 63 | LOG.debug("Login failed by username: " + username, e); 64 | return true; 65 | } 66 | return false; 67 | } 68 | 69 | protected OAuthResponse invalidUsernamePasswordResponse() throws OAuthSystemException { 70 | return OAuthResponse.errorResponse(HttpServletResponse.SC_BAD_REQUEST) 71 | .setError(OAuthError.TokenResponse.INVALID_GRANT) 72 | .setErrorDescription("Bad credentials") 73 | .buildJSONMessage(); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/oauth/token/ClientCredentialsTokenHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Andaily Information Technology Co. Ltd 3 | * www.andaily.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * Andaily Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with Andaily Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.oauth.token; 13 | 14 | import com.monkeyk.os.domain.oauth.AccessToken; 15 | import com.monkeyk.os.oauth.OAuthTokenxRequest; 16 | import com.monkeyk.os.oauth.validator.AbstractClientDetailsValidator; 17 | import com.monkeyk.os.oauth.validator.ClientCredentialsClientDetailsValidator; 18 | import com.monkeyk.os.web.WebUtils; 19 | import org.apache.oltu.oauth2.common.exception.OAuthProblemException; 20 | import org.apache.oltu.oauth2.common.exception.OAuthSystemException; 21 | import org.apache.oltu.oauth2.common.message.OAuthResponse; 22 | import org.apache.oltu.oauth2.common.message.types.GrantType; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | 26 | /** 27 | * 2015/7/3 28 | *

29 | * grant_type=client_credentials 30 | * 31 | * @author Shengzhao Li 32 | */ 33 | public class ClientCredentialsTokenHandler extends AbstractOAuthTokenHandler { 34 | 35 | private static final Logger LOG = LoggerFactory.getLogger(ClientCredentialsTokenHandler.class); 36 | 37 | 38 | @Override 39 | public boolean support(OAuthTokenxRequest tokenRequest) throws OAuthProblemException { 40 | final String grantType = tokenRequest.getGrantType(); 41 | return GrantType.CLIENT_CREDENTIALS.toString().equalsIgnoreCase(grantType); 42 | } 43 | 44 | /** 45 | * /oauth/token?client_id=credentials-client&client_secret=credentials-secret&grant_type=client_credentials&scope=read write 46 | *

47 | * Response access_token 48 | * If exist AccessToken and it is not expired, return it 49 | * otherwise, return a new AccessToken 50 | *

51 | * {"access_token":"38187f32-e4fb-4650-8e4a-99903b66f20e","token_type":"bearer","expires_in":7} 52 | */ 53 | @Override 54 | public void handleAfterValidation() throws OAuthProblemException, OAuthSystemException { 55 | 56 | AccessToken accessToken = oauthService.retrieveClientCredentialsAccessToken(clientDetails(), 57 | tokenRequest.getScopes()); 58 | final OAuthResponse tokenResponse = createTokenResponse(accessToken, false); 59 | 60 | LOG.debug("'client_credentials' response: {}", tokenResponse); 61 | WebUtils.writeOAuthJsonResponse(response, tokenResponse); 62 | 63 | 64 | } 65 | 66 | @Override 67 | protected AbstractClientDetailsValidator getValidator() { 68 | return new ClientCredentialsClientDetailsValidator(tokenRequest); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/oauth/token/PasswordTokenHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Andaily Information Technology Co. Ltd 3 | * www.andaily.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * Andaily Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with Andaily Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.oauth.token; 13 | 14 | import com.monkeyk.os.domain.oauth.AccessToken; 15 | import com.monkeyk.os.oauth.OAuthTokenxRequest; 16 | import com.monkeyk.os.oauth.validator.AbstractClientDetailsValidator; 17 | import com.monkeyk.os.oauth.validator.PasswordClientDetailsValidator; 18 | import com.monkeyk.os.web.WebUtils; 19 | import org.apache.oltu.oauth2.common.exception.OAuthProblemException; 20 | import org.apache.oltu.oauth2.common.exception.OAuthSystemException; 21 | import org.apache.oltu.oauth2.common.message.OAuthResponse; 22 | import org.apache.oltu.oauth2.common.message.types.GrantType; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | 26 | /** 27 | * 2015/7/3 28 | *

29 | * grant_type=password 30 | * 31 | * @author Shengzhao Li 32 | */ 33 | public class PasswordTokenHandler extends AbstractOAuthTokenHandler { 34 | 35 | private static final Logger LOG = LoggerFactory.getLogger(PasswordTokenHandler.class); 36 | 37 | 38 | @Override 39 | public boolean support(OAuthTokenxRequest tokenRequest) throws OAuthProblemException { 40 | final String grantType = tokenRequest.getGrantType(); 41 | return GrantType.PASSWORD.toString().equalsIgnoreCase(grantType); 42 | } 43 | 44 | @Override 45 | protected AbstractClientDetailsValidator getValidator() { 46 | return new PasswordClientDetailsValidator(tokenRequest); 47 | } 48 | 49 | /** 50 | * /oauth/token?client_id=mobile-client&client_secret=mobile&grant_type=password&scope=read,write&username=mobile&password=mobile 51 | *

52 | * Response access_token 53 | * If exist AccessToken and it is not expired, return it 54 | * otherwise, return a new AccessToken(include refresh_token) 55 | *

56 | * {"token_type":"Bearer","expires_in":33090,"refresh_token":"976aeaf7df1ee998f98f15acd1de63ea","access_token":"7811aff100eb7dadec132f45f1c01727"} 57 | */ 58 | @Override 59 | public void handleAfterValidation() throws OAuthProblemException, OAuthSystemException { 60 | 61 | AccessToken accessToken = oauthService.retrievePasswordAccessToken(clientDetails(), 62 | tokenRequest.getScopes(), tokenRequest.getUsername()); 63 | final OAuthResponse tokenResponse = createTokenResponse(accessToken, false); 64 | 65 | LOG.debug("'password' response: {}", tokenResponse); 66 | WebUtils.writeOAuthJsonResponse(response, tokenResponse); 67 | 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/web/WebUtils.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.web; 2 | 3 | import org.apache.commons.lang.StringUtils; 4 | import org.apache.oltu.oauth2.common.OAuth; 5 | import org.apache.oltu.oauth2.common.message.OAuthResponse; 6 | 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | import java.io.IOException; 10 | import java.io.PrintWriter; 11 | import java.util.Map; 12 | 13 | /** 14 | * @author Shengzhao Li 15 | */ 16 | public abstract class WebUtils { 17 | 18 | 19 | private WebUtils() { 20 | } 21 | 22 | 23 | public static void writeOAuthJsonResponse(HttpServletResponse response, OAuthResponse oAuthResponse) { 24 | 25 | final int responseStatus = oAuthResponse.getResponseStatus(); 26 | try { 27 | 28 | final Map headers = oAuthResponse.getHeaders(); 29 | for (String key : headers.keySet()) { 30 | response.addHeader(key, headers.get(key)); 31 | } 32 | // CORS setting 33 | response.setHeader("Access-Control-Allow-Origin", "*"); 34 | 35 | response.setContentType(OAuth.ContentType.JSON); //json 36 | response.setStatus(responseStatus); 37 | 38 | final PrintWriter out = response.getWriter(); 39 | out.print(oAuthResponse.getBody()); 40 | out.flush(); 41 | } catch (IOException e) { 42 | throw new IllegalStateException("Write OAuthResponse error", e); 43 | } 44 | } 45 | 46 | 47 | public static void writeOAuthQueryResponse(HttpServletResponse response, OAuthResponse oAuthResponse) { 48 | final String locationUri = oAuthResponse.getLocationUri(); 49 | try { 50 | 51 | final Map headers = oAuthResponse.getHeaders(); 52 | for (String key : headers.keySet()) { 53 | response.addHeader(key, headers.get(key)); 54 | } 55 | 56 | response.setStatus(oAuthResponse.getResponseStatus()); 57 | response.sendRedirect(locationUri); 58 | 59 | } catch (IOException e) { 60 | throw new IllegalStateException("Write OAuthResponse error", e); 61 | } 62 | } 63 | 64 | 65 | /** 66 | * Retrieve client ip address 67 | * 68 | * @param request HttpServletRequest 69 | * @return IP 70 | */ 71 | public static String retrieveClientIp(HttpServletRequest request) { 72 | String ip = request.getHeader("x-forwarded-for"); 73 | if (isUnAvailableIp(ip)) { 74 | ip = request.getHeader("Proxy-Client-IP"); 75 | } 76 | if (isUnAvailableIp(ip)) { 77 | ip = request.getHeader("WL-Proxy-Client-IP"); 78 | } 79 | if (isUnAvailableIp(ip)) { 80 | ip = request.getRemoteAddr(); 81 | } 82 | return ip; 83 | } 84 | 85 | private static boolean isUnAvailableIp(String ip) { 86 | return (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)); 87 | } 88 | } -------------------------------------------------------------------------------- /resources/src/main/java/com/monkeyk/os/web/WebUtils.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.web; 2 | 3 | import org.apache.commons.lang.StringUtils; 4 | import org.apache.oltu.oauth2.common.OAuth; 5 | import org.apache.oltu.oauth2.common.message.OAuthResponse; 6 | 7 | import javax.servlet.http.HttpServletRequest; 8 | import javax.servlet.http.HttpServletResponse; 9 | import java.io.IOException; 10 | import java.io.PrintWriter; 11 | import java.util.Map; 12 | 13 | /** 14 | * @author Shengzhao Li 15 | */ 16 | public abstract class WebUtils { 17 | 18 | 19 | private WebUtils() { 20 | } 21 | 22 | 23 | public static void writeOAuthJsonResponse(HttpServletResponse response, OAuthResponse oAuthResponse) { 24 | 25 | final int responseStatus = oAuthResponse.getResponseStatus(); 26 | try { 27 | 28 | final Map headers = oAuthResponse.getHeaders(); 29 | for (String key : headers.keySet()) { 30 | response.addHeader(key, headers.get(key)); 31 | } 32 | // CORS setting 33 | response.setHeader("Access-Control-Allow-Origin", "*"); 34 | 35 | response.setContentType(OAuth.ContentType.JSON); //json 36 | response.setStatus(responseStatus); 37 | 38 | final PrintWriter out = response.getWriter(); 39 | out.print(oAuthResponse.getBody()); 40 | out.flush(); 41 | } catch (IOException e) { 42 | throw new IllegalStateException("Write OAuthResponse error", e); 43 | } 44 | } 45 | 46 | 47 | public static void writeOAuthQueryResponse(HttpServletResponse response, OAuthResponse oAuthResponse) { 48 | final String locationUri = oAuthResponse.getLocationUri(); 49 | try { 50 | 51 | final Map headers = oAuthResponse.getHeaders(); 52 | for (String key : headers.keySet()) { 53 | response.addHeader(key, headers.get(key)); 54 | } 55 | 56 | response.setStatus(oAuthResponse.getResponseStatus()); 57 | response.sendRedirect(locationUri); 58 | 59 | } catch (IOException e) { 60 | throw new IllegalStateException("Write OAuthResponse error", e); 61 | } 62 | } 63 | 64 | 65 | /** 66 | * Retrieve client ip address 67 | * 68 | * @param request HttpServletRequest 69 | * @return IP 70 | */ 71 | public static String retrieveClientIp(HttpServletRequest request) { 72 | String ip = request.getHeader("x-forwarded-for"); 73 | if (isUnAvailableIp(ip)) { 74 | ip = request.getHeader("Proxy-Client-IP"); 75 | } 76 | if (isUnAvailableIp(ip)) { 77 | ip = request.getHeader("WL-Proxy-Client-IP"); 78 | } 79 | if (isUnAvailableIp(ip)) { 80 | ip = request.getRemoteAddr(); 81 | } 82 | return ip; 83 | } 84 | 85 | private static boolean isUnAvailableIp(String ip) { 86 | return (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)); 87 | } 88 | } -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/oauth/token/AbstractOAuthTokenHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Andaily Information Technology Co. Ltd 3 | * www.andaily.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * Andaily Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with Andaily Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.oauth.token; 13 | 14 | import com.monkeyk.os.web.WebUtils; 15 | import com.monkeyk.os.oauth.OAuthHandler; 16 | import com.monkeyk.os.oauth.OAuthTokenxRequest; 17 | import com.monkeyk.os.oauth.validator.AbstractClientDetailsValidator; 18 | import org.apache.oltu.oauth2.common.exception.OAuthProblemException; 19 | import org.apache.oltu.oauth2.common.exception.OAuthSystemException; 20 | import org.apache.oltu.oauth2.common.message.OAuthResponse; 21 | import org.slf4j.Logger; 22 | import org.slf4j.LoggerFactory; 23 | 24 | import javax.servlet.http.HttpServletResponse; 25 | 26 | /** 27 | * 2015/7/3 28 | * 29 | * @author Shengzhao Li 30 | */ 31 | public abstract class AbstractOAuthTokenHandler extends OAuthHandler implements OAuthTokenHandler { 32 | 33 | private static final Logger LOG = LoggerFactory.getLogger(AbstractOAuthTokenHandler.class); 34 | 35 | 36 | protected OAuthTokenxRequest tokenRequest; 37 | protected HttpServletResponse response; 38 | 39 | @Override 40 | public final void handle(OAuthTokenxRequest tokenRequest, HttpServletResponse response) throws OAuthProblemException, OAuthSystemException { 41 | this.tokenRequest = tokenRequest; 42 | this.response = response; 43 | 44 | //validate 45 | if (validateFailed()) { 46 | return; 47 | } 48 | 49 | 50 | handleAfterValidation(); 51 | } 52 | 53 | 54 | protected boolean validateFailed() throws OAuthSystemException { 55 | AbstractClientDetailsValidator validator = getValidator(); 56 | LOG.debug("Use [{}] validate client: {}", validator, tokenRequest.getClientId()); 57 | 58 | final OAuthResponse oAuthResponse = validator.validate(); 59 | return checkAndResponseValidateFailed(oAuthResponse); 60 | } 61 | 62 | protected boolean checkAndResponseValidateFailed(OAuthResponse oAuthResponse) { 63 | if (oAuthResponse != null) { 64 | LOG.debug("Validate OAuthAuthzRequest(client_id={}) failed", tokenRequest.getClientId()); 65 | WebUtils.writeOAuthJsonResponse(response, oAuthResponse); 66 | return true; 67 | } 68 | return false; 69 | } 70 | 71 | protected abstract AbstractClientDetailsValidator getValidator(); 72 | 73 | 74 | protected String clientId() { 75 | return tokenRequest.getClientId(); 76 | } 77 | 78 | protected abstract void handleAfterValidation() throws OAuthProblemException, OAuthSystemException; 79 | 80 | 81 | } 82 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/service/business/ClientCredentialsAccessTokenRetriever.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.service.business; 13 | 14 | import com.monkeyk.os.domain.oauth.AccessToken; 15 | import com.monkeyk.os.domain.oauth.ClientDetails; 16 | import org.apache.oltu.oauth2.common.exception.OAuthSystemException; 17 | import org.apache.oltu.oauth2.common.utils.OAuthUtils; 18 | import org.slf4j.Logger; 19 | import org.slf4j.LoggerFactory; 20 | 21 | import java.util.Set; 22 | 23 | /** 24 | * 2015/10/26 25 | * 26 | * @author Shengzhao Li 27 | */ 28 | public class ClientCredentialsAccessTokenRetriever extends AbstractAccessTokenHandler { 29 | 30 | private static final Logger LOG = LoggerFactory.getLogger(ClientCredentialsAccessTokenRetriever.class); 31 | 32 | 33 | private final ClientDetails clientDetails; 34 | private final Set scopes; 35 | 36 | public ClientCredentialsAccessTokenRetriever(ClientDetails clientDetails, Set scopes) { 37 | this.clientDetails = clientDetails; 38 | this.scopes = scopes; 39 | } 40 | 41 | 42 | public AccessToken retrieve() throws OAuthSystemException { 43 | 44 | String scope = OAuthUtils.encodeScopes(scopes); 45 | final String clientId = clientDetails.clientId(); 46 | //username = clientId 47 | 48 | final String authenticationId = authenticationIdGenerator.generate(clientId, clientId, scope); 49 | AccessToken accessToken = oauthRepository.findAccessToken(clientId, clientId, authenticationId); 50 | 51 | boolean needCreated = needCreated(clientId, accessToken); 52 | 53 | if (needCreated) { 54 | //Ignore refresh_token 55 | accessToken = createAndSaveAccessToken(clientDetails, false, clientId, authenticationId); 56 | LOG.debug("Create a new AccessToken: {}", accessToken); 57 | } 58 | 59 | return accessToken; 60 | } 61 | 62 | private boolean needCreated(String clientId, AccessToken accessToken) { 63 | boolean needCreate = false; 64 | if (accessToken == null) { 65 | needCreate = true; 66 | LOG.debug("Not found AccessToken from repository, will create a new one, client_id: {}", clientId); 67 | } else if (accessToken.tokenExpired()) { 68 | LOG.debug("Delete expired AccessToken: {} and create a new one, client_id: {}", accessToken, clientId); 69 | oauthRepository.deleteAccessToken(accessToken); 70 | needCreate = true; 71 | } else { 72 | LOG.debug("Use existed AccessToken: {}, client_id: {}", accessToken, clientId); 73 | } 74 | return needCreate; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/oauth/token/AuthorizationCodeTokenHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2013 Andaily Information Technology Co. Ltd 3 | * www.andaily.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * Andaily Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with Andaily Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.oauth.token; 13 | 14 | import com.monkeyk.os.domain.oauth.AccessToken; 15 | import com.monkeyk.os.web.WebUtils; 16 | import com.monkeyk.os.oauth.OAuthTokenxRequest; 17 | import com.monkeyk.os.oauth.validator.AbstractClientDetailsValidator; 18 | import com.monkeyk.os.oauth.validator.AuthorizationCodeClientDetailsValidator; 19 | import org.apache.oltu.oauth2.common.exception.OAuthProblemException; 20 | import org.apache.oltu.oauth2.common.exception.OAuthSystemException; 21 | import org.apache.oltu.oauth2.common.message.OAuthResponse; 22 | import org.apache.oltu.oauth2.common.message.types.GrantType; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | 26 | /** 27 | * 2015/7/3 28 | *

29 | * grant_type=authorization_code 30 | * 31 | * @author Shengzhao Li 32 | */ 33 | public class AuthorizationCodeTokenHandler extends AbstractOAuthTokenHandler { 34 | 35 | private static final Logger LOG = LoggerFactory.getLogger(AuthorizationCodeTokenHandler.class); 36 | 37 | @Override 38 | public boolean support(OAuthTokenxRequest tokenRequest) throws OAuthProblemException { 39 | final String grantType = tokenRequest.getGrantType(); 40 | return GrantType.AUTHORIZATION_CODE.toString().equalsIgnoreCase(grantType); 41 | } 42 | 43 | /* 44 | * 45 | * /oauth/token?client_id=unity-client&client_secret=unity&grant_type=authorization_code&code=zLl170&redirect_uri=redirect_uri 46 | * */ 47 | @Override 48 | public void handleAfterValidation() throws OAuthProblemException, OAuthSystemException { 49 | 50 | //response token, always new 51 | responseToken(); 52 | 53 | //remove code lastly 54 | removeCode(); 55 | } 56 | 57 | private void removeCode() { 58 | final String code = tokenRequest.getCode(); 59 | final boolean result = oauthService.removeOauthCode(code, clientDetails()); 60 | LOG.debug("Remove code: {} result: {}", code, result); 61 | } 62 | 63 | private void responseToken() throws OAuthSystemException { 64 | AccessToken accessToken = oauthService.retrieveAuthorizationCodeAccessToken(clientDetails(), tokenRequest.getCode()); 65 | final OAuthResponse tokenResponse = createTokenResponse(accessToken, false); 66 | 67 | LOG.debug("'authorization_code' response: {}", tokenResponse); 68 | WebUtils.writeOAuthJsonResponse(response, tokenResponse); 69 | } 70 | 71 | @Override 72 | protected AbstractClientDetailsValidator getValidator() { 73 | return new AuthorizationCodeClientDetailsValidator(tokenRequest); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/infrastructure/UsersRedisRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.infrastructure; 13 | 14 | import com.monkeyk.os.domain.users.Roles; 15 | import com.monkeyk.os.domain.users.Users; 16 | import com.monkeyk.os.domain.users.UsersRepository; 17 | import com.monkeyk.os.infrastructure.cache.AbstractCacheSupport; 18 | 19 | import static com.monkeyk.os.infrastructure.cache.CacheKeyGenerator.*; 20 | 21 | import com.monkeyk.os.infrastructure.cache.CacheNames; 22 | import com.monkeyk.os.infrastructure.jdbc.UsersJdbcRepository; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | import org.springframework.beans.factory.annotation.Autowired; 26 | import org.springframework.cache.Cache; 27 | import org.springframework.cache.CacheManager; 28 | import org.springframework.stereotype.Repository; 29 | 30 | import java.util.List; 31 | 32 | /** 33 | * 2015/10/26 34 | * 35 | * @author Shengzhao Li 36 | */ 37 | @Repository("usersRedisRepository") 38 | public class UsersRedisRepository extends AbstractCacheSupport implements UsersRepository { 39 | 40 | 41 | private static final Logger LOG = LoggerFactory.getLogger(UsersRedisRepository.class); 42 | 43 | @Autowired 44 | private UsersJdbcRepository usersRepository; 45 | 46 | @Autowired 47 | private CacheManager cacheManager; 48 | 49 | 50 | @Override 51 | public Users findUsersByUsername(String username) { 52 | 53 | final Cache usersCache = getUsersCache(); 54 | 55 | final String key = generateUsersKey(username); 56 | Users users = (Users) getFromCache(usersCache, key); 57 | 58 | if (users == null) { 59 | users = usersRepository.findUsersByUsername(username); 60 | putToCache(usersCache, key, users); 61 | LOG.debug("Load Users[{}] from DB and cache it, key = {}", users, key); 62 | } 63 | 64 | return users; 65 | } 66 | 67 | @Override 68 | public List findRolesByUsername(String username) { 69 | 70 | final Cache usersCache = getUsersCache(); 71 | 72 | final String key = generateUserRolesKey(username); 73 | @SuppressWarnings("unchecked") 74 | List rolesList = (List) getFromCache(usersCache, key); 75 | 76 | if (rolesList == null) { 77 | rolesList = usersRepository.findRolesByUsername(username); 78 | putToCache(usersCache, key, rolesList); 79 | LOG.debug("Load User roles[{}] from DB and cache it, key = {}", rolesList, key); 80 | } 81 | 82 | return rolesList; 83 | } 84 | 85 | 86 | private Cache getUsersCache() { 87 | return cacheManager.getCache(CacheNames.USERS_CACHE); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /authz/src/main/java/com/monkeyk/os/service/business/PasswordAccessTokenRetriever.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.service.business; 13 | 14 | import com.monkeyk.os.domain.oauth.AccessToken; 15 | import com.monkeyk.os.domain.oauth.ClientDetails; 16 | import org.apache.oltu.oauth2.common.exception.OAuthSystemException; 17 | import org.apache.oltu.oauth2.common.utils.OAuthUtils; 18 | import org.slf4j.Logger; 19 | import org.slf4j.LoggerFactory; 20 | 21 | import java.util.Set; 22 | 23 | /** 24 | * 2015/10/26 25 | * 26 | * @author Shengzhao Li 27 | */ 28 | public class PasswordAccessTokenRetriever extends AbstractAccessTokenHandler { 29 | 30 | 31 | private static final Logger LOG = LoggerFactory.getLogger(PasswordAccessTokenRetriever.class); 32 | 33 | 34 | private final ClientDetails clientDetails; 35 | private final Set scopes; 36 | private final String username; 37 | 38 | public PasswordAccessTokenRetriever(ClientDetails clientDetails, Set scopes, String username) { 39 | this.clientDetails = clientDetails; 40 | this.scopes = scopes; 41 | this.username = username; 42 | } 43 | 44 | //grant_type=password AccessToken 45 | public AccessToken retrieve() throws OAuthSystemException { 46 | 47 | String scope = OAuthUtils.encodeScopes(scopes); 48 | final String clientId = clientDetails.clientId(); 49 | 50 | final String authenticationId = authenticationIdGenerator.generate(clientId, username, scope); 51 | AccessToken accessToken = oauthRepository.findAccessToken(clientId, username, authenticationId); 52 | 53 | boolean needCreated = needCreated(clientId, accessToken); 54 | 55 | if (needCreated) { 56 | accessToken = createAndSaveAccessToken(clientDetails, clientDetails.supportRefreshToken(), username, authenticationId); 57 | LOG.debug("Create a new AccessToken: {}", accessToken); 58 | } 59 | 60 | return accessToken; 61 | } 62 | 63 | private boolean needCreated(String clientId, AccessToken accessToken) { 64 | boolean needCreate = false; 65 | 66 | if (accessToken == null) { 67 | needCreate = true; 68 | LOG.debug("Not found AccessToken from repository, will create a new one, client_id: {}", clientId); 69 | } else if (accessToken.tokenExpired()) { 70 | LOG.debug("Delete expired AccessToken: {} and create a new one, client_id: {}", accessToken, clientId); 71 | oauthRepository.deleteAccessToken(accessToken); 72 | needCreate = true; 73 | } else { 74 | LOG.debug("Use existed AccessToken: {}, client_id: {}", accessToken, clientId); 75 | } 76 | return needCreate; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /resources/src/main/java/com/monkeyk/os/oauth/resources/MkkOAuthRSProvider.java: -------------------------------------------------------------------------------- 1 | package com.monkeyk.os.oauth.resources; 2 | 3 | import com.monkeyk.os.domain.oauth.AccessToken; 4 | import com.monkeyk.os.domain.oauth.ClientDetails; 5 | import com.monkeyk.os.domain.rs.RSOAuthClient; 6 | import com.monkeyk.os.domain.shared.BeanProvider; 7 | import com.monkeyk.os.service.OAuthRSService; 8 | import org.apache.oltu.oauth2.common.error.OAuthError; 9 | import org.apache.oltu.oauth2.common.exception.OAuthProblemException; 10 | import org.apache.oltu.oauth2.rsfilter.OAuthDecision; 11 | import org.apache.oltu.oauth2.rsfilter.OAuthRSProvider; 12 | import org.slf4j.Logger; 13 | import org.slf4j.LoggerFactory; 14 | 15 | import javax.servlet.http.HttpServletRequest; 16 | 17 | /** 18 | * 2015/7/8 19 | * 20 | * @author Shengzhao Li 21 | */ 22 | public class MkkOAuthRSProvider implements OAuthRSProvider { 23 | 24 | private static final Logger LOG = LoggerFactory.getLogger(MkkOAuthRSProvider.class); 25 | 26 | 27 | private transient OAuthRSService rsService = BeanProvider.getBean(OAuthRSService.class); 28 | 29 | @Override 30 | public OAuthDecision validateRequest(String rsId, String token, HttpServletRequest req) throws OAuthProblemException { 31 | LOG.debug("Call OAuthRSProvider, rsId: {},token: {},req: {}", new Object[]{rsId, token, req}); 32 | 33 | AccessToken accessToken = rsService.loadAccessTokenByTokenId(token); 34 | validateToken(token, accessToken); 35 | 36 | ClientDetails clientDetails = rsService.loadClientDetails(accessToken.clientId(), rsId); 37 | validateClientDetails(token, accessToken, clientDetails); 38 | 39 | 40 | //TODO: It is OK? 41 | MkkOAuthDecision oAuthDecision = new MkkOAuthDecision().setOAuthClient(new RSOAuthClient(clientDetails)); 42 | oAuthDecision.setPrincipal(new MkkOAuthPrincipal(accessToken.username())); 43 | oAuthDecision.setAuthorized(true); 44 | 45 | return oAuthDecision; 46 | } 47 | 48 | private void validateClientDetails(String token, AccessToken accessToken, ClientDetails clientDetails) throws OAuthProblemException { 49 | if (clientDetails == null || clientDetails.archived()) { 50 | LOG.debug("Invalid ClientDetails: {} by client_id: {}, it is null or archived", clientDetails, accessToken.clientId()); 51 | throw OAuthProblemException.error(OAuthError.ResourceResponse.INVALID_TOKEN) 52 | .description("Invalid client by token: " + token); 53 | } 54 | } 55 | 56 | private void validateToken(String token, AccessToken accessToken) throws OAuthProblemException { 57 | if (accessToken == null) { 58 | LOG.debug("Invalid access_token: {}, because it is null", token); 59 | throw OAuthProblemException.error(OAuthError.ResourceResponse.INVALID_TOKEN) 60 | .description("Invalid access_token: " + token); 61 | } 62 | if (accessToken.tokenExpired()) { 63 | LOG.debug("Invalid access_token: {}, because it is expired", token); 64 | throw OAuthProblemException.error(OAuthError.ResourceResponse.EXPIRED_TOKEN) 65 | .description("Expired access_token: " + token); 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /resources/src/main/java/com/monkeyk/os/infrastructure/UsersRSRedisRepository.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 MONKEYK Information Technology Co. Ltd 3 | * www.monkeyk.com 4 | * All rights reserved. 5 | * 6 | * This software is the confidential and proprietary information of 7 | * MONKEYK Information Technology Co. Ltd ("Confidential Information"). 8 | * You shall not disclose such Confidential Information and shall use 9 | * it only in accordance with the terms of the license agreement you 10 | * entered into with MONKEYK Information Technology Co. Ltd. 11 | */ 12 | package com.monkeyk.os.infrastructure; 13 | 14 | import com.monkeyk.os.domain.users.Roles; 15 | import com.monkeyk.os.domain.users.Users; 16 | import com.monkeyk.os.domain.users.UsersRepository; 17 | import com.monkeyk.os.infrastructure.cache.AbstractCacheSupport; 18 | import com.monkeyk.os.infrastructure.cache.CacheNames; 19 | import com.monkeyk.os.infrastructure.jdbc.UsersRSJdbcRepository; 20 | import org.slf4j.Logger; 21 | import org.slf4j.LoggerFactory; 22 | import org.springframework.beans.factory.annotation.Autowired; 23 | import org.springframework.cache.Cache; 24 | import org.springframework.cache.CacheManager; 25 | import org.springframework.stereotype.Repository; 26 | 27 | import java.util.List; 28 | 29 | import static com.monkeyk.os.infrastructure.cache.CacheKeyGenerator.generateUserRolesKey; 30 | import static com.monkeyk.os.infrastructure.cache.CacheKeyGenerator.generateUsersKey; 31 | 32 | /** 33 | * 2015/10/27 34 | * 35 | * @author Shengzhao Li 36 | */ 37 | @Repository("usersRSRedisRepository") 38 | public class UsersRSRedisRepository extends AbstractCacheSupport implements UsersRepository { 39 | 40 | 41 | private static final Logger LOG = LoggerFactory.getLogger(UsersRSRedisRepository.class); 42 | 43 | @Autowired 44 | private UsersRSJdbcRepository usersRepository; 45 | 46 | @Autowired 47 | private CacheManager cacheManager; 48 | 49 | 50 | @Override 51 | public Users findUsersByUsername(String username) { 52 | 53 | final Cache usersCache = getUsersCache(); 54 | 55 | final String key = generateUsersKey(username); 56 | Users users = (Users) getFromCache(usersCache, key); 57 | 58 | if (users == null) { 59 | users = usersRepository.findUsersByUsername(username); 60 | putToCache(usersCache, key, users); 61 | LOG.debug("Load Users[{}] from DB and cache it, key = {}", users, key); 62 | } 63 | 64 | return users; 65 | } 66 | 67 | @Override 68 | public List findRolesByUsername(String username) { 69 | 70 | final Cache usersCache = getUsersCache(); 71 | 72 | final String key = generateUserRolesKey(username); 73 | @SuppressWarnings("unchecked") 74 | List rolesList = (List) getFromCache(usersCache, key); 75 | 76 | if (rolesList == null) { 77 | rolesList = usersRepository.findRolesByUsername(username); 78 | putToCache(usersCache, key, rolesList); 79 | LOG.debug("Load User roles[{}] from DB and cache it, key = {}", rolesList, key); 80 | } 81 | 82 | return rolesList; 83 | } 84 | 85 | 86 | private Cache getUsersCache() { 87 | return cacheManager.getCache(CacheNames.USERS_CACHE); 88 | } 89 | 90 | } 91 | --------------------------------------------------------------------------------