├── cas
├── .gitignore
├── src
│ ├── main
│ │ ├── webapp
│ │ │ ├── META-INF
│ │ │ │ └── MANIFEST.MF
│ │ │ └── WEB-INF
│ │ │ │ ├── views
│ │ │ │ ├── index.jsp
│ │ │ │ └── login.jsp
│ │ │ │ └── web.xml
│ │ ├── java
│ │ │ └── cas
│ │ │ │ ├── cdao
│ │ │ │ ├── package-info.java
│ │ │ │ ├── CacheDao.java
│ │ │ │ ├── factory
│ │ │ │ │ └── CacheDaoFactory.java
│ │ │ │ └── impl
│ │ │ │ │ └── RedisCacheDao.java
│ │ │ │ ├── dao
│ │ │ │ └── UserDao.java
│ │ │ │ ├── mq
│ │ │ │ ├── receiver
│ │ │ │ │ ├── Receiver.java
│ │ │ │ │ └── LogoutMessageReceiver.java
│ │ │ │ ├── sender
│ │ │ │ │ ├── Sender.java
│ │ │ │ │ └── LogoutMessageSender.java
│ │ │ │ ├── queue
│ │ │ │ │ ├── MessageQueue.java
│ │ │ │ │ └── RedisMessageQueue.java
│ │ │ │ ├── message
│ │ │ │ │ ├── Message.java
│ │ │ │ │ └── LogoutMessage.java
│ │ │ │ └── support
│ │ │ │ │ └── LogoutReceiverDispatcher.java
│ │ │ │ ├── custom
│ │ │ │ └── component
│ │ │ │ │ ├── session
│ │ │ │ │ ├── CustomSessionProcessor.java
│ │ │ │ │ ├── DefaultCacheHttpSession.java
│ │ │ │ │ ├── HttpSessionWrapper.java
│ │ │ │ │ └── BufferedCacheHttpSession.java
│ │ │ │ │ ├── factory
│ │ │ │ │ └── CacheHttpSessionFactory.java
│ │ │ │ │ └── request
│ │ │ │ │ └── CustomHttpServletRequest.java
│ │ │ │ ├── service
│ │ │ │ └── UserService.java
│ │ │ │ ├── support
│ │ │ │ └── ConfigLoader.java
│ │ │ │ ├── mapping
│ │ │ │ └── UserMapping.xml
│ │ │ │ ├── models
│ │ │ │ └── User.java
│ │ │ │ ├── utils
│ │ │ │ ├── QRCodeUtils.java
│ │ │ │ ├── CookieUtil.java
│ │ │ │ ├── RedisUtil.java
│ │ │ │ ├── JsonUtils.java
│ │ │ │ └── HttpRequest.java
│ │ │ │ ├── controller
│ │ │ │ ├── PublicController.java
│ │ │ │ └── SystemController.java
│ │ │ │ └── filter
│ │ │ │ ├── LoginInterceptor.java
│ │ │ │ ├── AuthenticationFilter.java
│ │ │ │ └── CacheSessionFilter.java
│ │ └── resources
│ │ │ ├── jdbc.properties
│ │ │ ├── cas-config.properties
│ │ │ ├── table-user.sql
│ │ │ ├── logback.xml
│ │ │ ├── spring-component.xml
│ │ │ ├── spring-mybatis.xml
│ │ │ └── springmvc.xml
│ └── test
│ │ └── java
│ │ └── cas
│ │ └── test
│ │ ├── component
│ │ ├── DefaultCacheHttpSessionTest.java
│ │ ├── Person.java
│ │ ├── BufferedCacheHttpSessionTest.java
│ │ └── QRCodeTest.java
│ │ └── service
│ │ └── UserServiceTest.java
└── pom.xml
├── CasAndroidClient
├── app
│ ├── .gitignore
│ ├── libs
│ │ ├── core-3.0.0.jar
│ │ └── javase-3.0.0.jar
│ ├── src
│ │ ├── main
│ │ │ ├── res
│ │ │ │ ├── values
│ │ │ │ │ ├── strings.xml
│ │ │ │ │ ├── colors.xml
│ │ │ │ │ ├── dimens.xml
│ │ │ │ │ ├── ids.xml
│ │ │ │ │ └── styles.xml
│ │ │ │ ├── raw
│ │ │ │ │ └── beep.ogg
│ │ │ │ ├── drawable
│ │ │ │ │ ├── url.png
│ │ │ │ │ ├── ic_scan_album.png
│ │ │ │ │ ├── ic_scan_black.png
│ │ │ │ │ ├── ic_scan_green.png
│ │ │ │ │ ├── ic_scan_light.png
│ │ │ │ │ ├── ic_scan_line.png
│ │ │ │ │ ├── ic_scan_white.png
│ │ │ │ │ ├── ic_scan_top_left.png
│ │ │ │ │ ├── global_loading_bg.png
│ │ │ │ │ ├── ic_arrow_left_white.png
│ │ │ │ │ ├── ic_scan_bottom_left.png
│ │ │ │ │ ├── ic_scan_light_off.png
│ │ │ │ │ ├── ic_scan_top_right.png
│ │ │ │ │ ├── ic_scan_bottom_right.png
│ │ │ │ │ ├── global_progressbar_loading.png
│ │ │ │ │ ├── loading_gray_ani.xml
│ │ │ │ │ ├── selector_scan_light.xml
│ │ │ │ │ └── shape_circle_black.xml
│ │ │ │ ├── mipmap-hdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-mdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── mipmap-xxxhdpi
│ │ │ │ │ └── ic_launcher.png
│ │ │ │ ├── menu
│ │ │ │ │ └── main_menu.xml
│ │ │ │ ├── values-w820dp
│ │ │ │ │ └── dimens.xml
│ │ │ │ └── layout
│ │ │ │ │ ├── progress_loding_layout.xml
│ │ │ │ │ ├── activity_main.xml
│ │ │ │ │ ├── activity_login.xml
│ │ │ │ │ └── activity_capture.xml
│ │ │ ├── java
│ │ │ │ └── com
│ │ │ │ │ └── casandroidclient
│ │ │ │ │ ├── component
│ │ │ │ │ ├── CustomAlertDialogFactory.java
│ │ │ │ │ ├── DecodeFormatManager.java
│ │ │ │ │ ├── LoadingDialog.java
│ │ │ │ │ ├── PreviewCallback.java
│ │ │ │ │ ├── OpenCameraInterface.java
│ │ │ │ │ ├── DecodeThread.java
│ │ │ │ │ ├── AutoFocusManager.java
│ │ │ │ │ ├── DecodeHandler.java
│ │ │ │ │ ├── CameraManager.java
│ │ │ │ │ └── CameraConfigurationManager.java
│ │ │ │ │ ├── LoginActivity.java
│ │ │ │ │ ├── utils
│ │ │ │ │ ├── SharedPreferenceUtils.java
│ │ │ │ │ ├── HttpRequest.java
│ │ │ │ │ ├── InactivityTimer.java
│ │ │ │ │ ├── CaptureActivityHandler.java
│ │ │ │ │ └── BeepManager.java
│ │ │ │ │ └── MainActivity.java
│ │ │ └── AndroidManifest.xml
│ │ ├── test
│ │ │ └── java
│ │ │ │ └── com
│ │ │ │ └── casandroidclient
│ │ │ │ └── ExampleUnitTest.java
│ │ └── androidTest
│ │ │ └── java
│ │ │ └── com
│ │ │ └── casandroidclient
│ │ │ └── ApplicationTest.java
│ ├── proguard-rules.pro
│ └── build.gradle
├── settings.gradle
├── .gitignore
├── gradle
│ └── wrapper
│ │ ├── gradle-wrapper.jar
│ │ └── gradle-wrapper.properties
├── build.gradle
├── gradle.properties
├── gradlew.bat
└── gradlew
├── client
├── WebRoot
│ ├── WEB-INF
│ │ ├── classes
│ │ │ └── .gitignore
│ │ ├── lib
│ │ │ ├── fastjson-1.2.5.jar
│ │ │ └── commons-lang-2.6.jar
│ │ └── web.xml
│ ├── META-INF
│ │ └── MANIFEST.MF
│ └── index.jsp
└── src
│ └── client
│ ├── model
│ └── User.java
│ ├── listener
│ └── SessionLifecycleListener.java
│ ├── cas
│ └── component
│ │ └── LogedSessionManager.java
│ ├── filter
│ ├── LogoutFilter.java
│ └── AuthenticationFilter.java
│ └── utils
│ ├── JsonUtils.java
│ └── HttpRequest.java
├── .gitignore
└── README.md
/cas/.gitignore:
--------------------------------------------------------------------------------
1 | /target
2 |
--------------------------------------------------------------------------------
/CasAndroidClient/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/CasAndroidClient/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/client/WebRoot/WEB-INF/classes/.gitignore:
--------------------------------------------------------------------------------
1 | /client
2 |
--------------------------------------------------------------------------------
/client/WebRoot/META-INF/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 | Class-Path:
3 |
4 |
--------------------------------------------------------------------------------
/cas/src/main/webapp/META-INF/MANIFEST.MF:
--------------------------------------------------------------------------------
1 | Manifest-Version: 1.0
2 | Class-Path:
3 |
4 |
--------------------------------------------------------------------------------
/CasAndroidClient/app/libs/core-3.0.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nameof/redis-session/HEAD/CasAndroidClient/app/libs/core-3.0.0.jar
--------------------------------------------------------------------------------
/CasAndroidClient/app/libs/javase-3.0.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nameof/redis-session/HEAD/CasAndroidClient/app/libs/javase-3.0.0.jar
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | CasAndroidClient
3 |
4 |
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/raw/beep.ogg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nameof/redis-session/HEAD/CasAndroidClient/app/src/main/res/raw/beep.ogg
--------------------------------------------------------------------------------
/cas/src/main/java/cas/cdao/package-info.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Cache Data Access Object 缓存数据访问对象
3 | * @author ChengPan
4 | */
5 | package cas.cdao;
--------------------------------------------------------------------------------
/client/WebRoot/WEB-INF/lib/fastjson-1.2.5.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nameof/redis-session/HEAD/client/WebRoot/WEB-INF/lib/fastjson-1.2.5.jar
--------------------------------------------------------------------------------
/cas/src/main/resources/jdbc.properties:
--------------------------------------------------------------------------------
1 | url=jdbc\:mysql\://127.0.0.1\:3306/java
2 | username=root
3 | password=root
4 | driver=com.mysql.jdbc.Driver
--------------------------------------------------------------------------------
/client/WebRoot/WEB-INF/lib/commons-lang-2.6.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nameof/redis-session/HEAD/client/WebRoot/WEB-INF/lib/commons-lang-2.6.jar
--------------------------------------------------------------------------------
/CasAndroidClient/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /build
8 | /captures
9 |
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/drawable/url.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nameof/redis-session/HEAD/CasAndroidClient/app/src/main/res/drawable/url.png
--------------------------------------------------------------------------------
/CasAndroidClient/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nameof/redis-session/HEAD/CasAndroidClient/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/drawable/ic_scan_album.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nameof/redis-session/HEAD/CasAndroidClient/app/src/main/res/drawable/ic_scan_album.png
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/drawable/ic_scan_black.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nameof/redis-session/HEAD/CasAndroidClient/app/src/main/res/drawable/ic_scan_black.png
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/drawable/ic_scan_green.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nameof/redis-session/HEAD/CasAndroidClient/app/src/main/res/drawable/ic_scan_green.png
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/drawable/ic_scan_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nameof/redis-session/HEAD/CasAndroidClient/app/src/main/res/drawable/ic_scan_light.png
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/drawable/ic_scan_line.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nameof/redis-session/HEAD/CasAndroidClient/app/src/main/res/drawable/ic_scan_line.png
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/drawable/ic_scan_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nameof/redis-session/HEAD/CasAndroidClient/app/src/main/res/drawable/ic_scan_white.png
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nameof/redis-session/HEAD/CasAndroidClient/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nameof/redis-session/HEAD/CasAndroidClient/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/drawable/ic_scan_top_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nameof/redis-session/HEAD/CasAndroidClient/app/src/main/res/drawable/ic_scan_top_left.png
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nameof/redis-session/HEAD/CasAndroidClient/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nameof/redis-session/HEAD/CasAndroidClient/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/cas/src/main/resources/cas-config.properties:
--------------------------------------------------------------------------------
1 | cache.dao.impl.class=cas.cdao.impl.RedisCacheDao
2 | cache.httpsession.impl.class=cas.custom.component.session.DefaultCacheHttpSession
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/drawable/global_loading_bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nameof/redis-session/HEAD/CasAndroidClient/app/src/main/res/drawable/global_loading_bg.png
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/drawable/ic_arrow_left_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nameof/redis-session/HEAD/CasAndroidClient/app/src/main/res/drawable/ic_arrow_left_white.png
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/drawable/ic_scan_bottom_left.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nameof/redis-session/HEAD/CasAndroidClient/app/src/main/res/drawable/ic_scan_bottom_left.png
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/drawable/ic_scan_light_off.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nameof/redis-session/HEAD/CasAndroidClient/app/src/main/res/drawable/ic_scan_light_off.png
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/drawable/ic_scan_top_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nameof/redis-session/HEAD/CasAndroidClient/app/src/main/res/drawable/ic_scan_top_right.png
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nameof/redis-session/HEAD/CasAndroidClient/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/drawable/ic_scan_bottom_right.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nameof/redis-session/HEAD/CasAndroidClient/app/src/main/res/drawable/ic_scan_bottom_right.png
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/drawable/global_progressbar_loading.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nameof/redis-session/HEAD/CasAndroidClient/app/src/main/res/drawable/global_progressbar_loading.png
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/cas/src/main/java/cas/dao/UserDao.java:
--------------------------------------------------------------------------------
1 | package cas.dao;
2 |
3 | import org.springframework.stereotype.Repository;
4 |
5 | import cas.models.User;
6 |
7 | @Repository
8 | public interface UserDao {
9 |
10 | User getUserByName(String userName);
11 | }
12 |
--------------------------------------------------------------------------------
/CasAndroidClient/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Mon Dec 28 10:00:20 PST 2015
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-all.zip
7 |
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/drawable/loading_gray_ani.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/menu/main_menu.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/drawable/selector_scan_light.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/client/WebRoot/index.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2 |
3 |
4 |
5 |
6 |
7 |
8 | welcome to client! ${sessionScope.user.name}
9 | 注销登录
10 |
11 |
12 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Compiled class file
2 | *.class
3 |
4 | # Log file
5 | *.log
6 |
7 | # BlueJ files
8 | *.ctxt
9 |
10 | # Mobile Tools for Java (J2ME)
11 | .mtj.tmp/
12 |
13 | # Package Files #
14 | *.jar
15 | *.war
16 | *.ear
17 | *.zip
18 | *.tar.gz
19 | *.rar
20 |
21 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
22 | hs_err_pid*
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/drawable/shape_circle_black.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
7 |
9 |
10 |
--------------------------------------------------------------------------------
/cas/src/main/webapp/WEB-INF/views/index.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2 |
3 |
4 |
5 |
6 | 欢迎
7 |
8 |
9 | welcome ! ${user.name}
10 | 注销登录
11 |
12 |
13 |
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/test/java/com/casandroidclient/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.casandroidclient;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * To work on unit tests, switch the Test Artifact in the Build Variants view.
9 | */
10 | public class ExampleUnitTest {
11 | @Test
12 | public void addition_isCorrect() throws Exception {
13 | assertEquals(4, 2 + 2);
14 | }
15 | }
--------------------------------------------------------------------------------
/cas/src/main/java/cas/mq/receiver/Receiver.java:
--------------------------------------------------------------------------------
1 | package cas.mq.receiver;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 |
6 | import cas.mq.message.Message;
7 |
8 | /**
9 | * 消息接收者
10 | * @author ChengPan
11 | */
12 | public abstract class Receiver {
13 |
14 | protected final Logger logger = LoggerFactory.getLogger(getClass());
15 |
16 | public abstract void handleMessage(Message message);
17 | }
18 |
--------------------------------------------------------------------------------
/cas/src/main/java/cas/mq/sender/Sender.java:
--------------------------------------------------------------------------------
1 | package cas.mq.sender;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 |
6 | import cas.mq.message.Message;
7 |
8 | /**
9 | * 消息发送者
10 | *
11 | * @author ChengPan
12 | */
13 | public abstract class Sender {
14 |
15 | protected final Logger logger = LoggerFactory.getLogger(getClass());
16 |
17 | public abstract void sendMessage(Message message);
18 | }
19 |
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/androidTest/java/com/casandroidclient/ApplicationTest.java:
--------------------------------------------------------------------------------
1 | package com.casandroidclient;
2 |
3 | import android.app.Application;
4 | import android.test.ApplicationTestCase;
5 |
6 | /**
7 | * Testing Fundamentals
8 | */
9 | public class ApplicationTest extends ApplicationTestCase {
10 | public ApplicationTest() {
11 | super(Application.class);
12 | }
13 | }
--------------------------------------------------------------------------------
/cas/src/main/java/cas/custom/component/session/CustomSessionProcessor.java:
--------------------------------------------------------------------------------
1 | package cas.custom.component.session;
2 |
3 | /**
4 | *
5 | * 用于自定义Session的前置、后置处理
6 | *
7 | * @author ChengPan
8 | *
9 | */
10 | public interface CustomSessionProcessor {
11 |
12 | /**
13 | * 用于自定义Session的初始化工作,例如从缓存中加载已有的Session属性
14 | */
15 | void initialize();
16 |
17 | /**
18 | * 用于自定义Session的后置处理工作,例如在请求处理完成之后,将自定义Session的属性提交同步到缓存中
19 | */
20 | void commit();
21 | }
22 |
--------------------------------------------------------------------------------
/cas/src/main/java/cas/mq/queue/MessageQueue.java:
--------------------------------------------------------------------------------
1 | package cas.mq.queue;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 |
6 | import cas.mq.message.Message;
7 |
8 | /**
9 | * 消息队列
10 | *
11 | * @author ChengPan
12 | */
13 | public abstract class MessageQueue {
14 |
15 | protected final Logger logger = LoggerFactory.getLogger(getClass());
16 |
17 | public abstract void push(Message message);
18 |
19 | public abstract Message pop();
20 | }
21 |
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/values/ids.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/cas/src/test/java/cas/test/component/DefaultCacheHttpSessionTest.java:
--------------------------------------------------------------------------------
1 | package cas.test.component;
2 |
3 | import org.junit.Test;
4 |
5 | import cas.custom.component.session.DefaultCacheHttpSession;
6 |
7 | public class DefaultCacheHttpSessionTest {
8 |
9 |
10 | @Test
11 | public void testOperatAttribute(){
12 | DefaultCacheHttpSession session = new DefaultCacheHttpSession(null, "token");
13 | Person p = new Person("程攀",123);
14 | session.setAttribute("userInfo", p);
15 | System.out.println(session.getAttribute("userInfo").toString());
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/cas/src/main/java/cas/mq/sender/LogoutMessageSender.java:
--------------------------------------------------------------------------------
1 | package cas.mq.sender;
2 |
3 | import cas.mq.message.Message;
4 | import cas.mq.queue.RedisMessageQueue;
5 |
6 | /**
7 | * 注销消息发送者
8 | *
9 | * @author ChengPan
10 | */
11 | public class LogoutMessageSender extends Sender{
12 |
13 | private static final String LOGOUT_QUEUE_NAME = "logoutQueue";
14 |
15 | private static RedisMessageQueue queue = new RedisMessageQueue(LOGOUT_QUEUE_NAME);
16 |
17 | @Override
18 | public void sendMessage(Message message) {
19 | queue.push(message);
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/CasAndroidClient/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:2.0.0'
9 | // NOTE: Do not place your application dependencies here; they belong
10 | // in the individual module build.gradle files
11 | }
12 | }
13 |
14 | allprojects {
15 | repositories {
16 | jcenter()
17 | }
18 | }
19 |
20 | task clean(type: Delete) {
21 | delete rootProject.buildDir
22 | }
23 |
--------------------------------------------------------------------------------
/cas/src/main/java/cas/service/UserService.java:
--------------------------------------------------------------------------------
1 | package cas.service;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.stereotype.Service;
5 |
6 | import cas.dao.UserDao;
7 | import cas.models.User;
8 |
9 | @Service
10 | public class UserService {
11 | @Autowired
12 | private UserDao userDao;
13 |
14 | public User verifyUserLogin(User inputUser) {
15 | User user = userDao.getUserByName(inputUser.getName());
16 | if (user == null || !user.getPasswd().equals(inputUser.getPasswd())) {
17 | return null;
18 | }
19 | user.setPasswd(null);
20 | return user;
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
14 |
15 |
--------------------------------------------------------------------------------
/cas/src/main/java/cas/support/ConfigLoader.java:
--------------------------------------------------------------------------------
1 | package cas.support;
2 |
3 | import java.io.IOException;
4 | import java.util.Properties;
5 |
6 | /**
7 | * 载入cas-config.properties文件中的配置信息
8 | *
9 | * @author ChengPan
10 | */
11 | public class ConfigLoader {
12 | private ConfigLoader() {}
13 |
14 | private static final Properties properties = new Properties();
15 |
16 | static {
17 | try {
18 | properties.load(ConfigLoader.class.getResourceAsStream("/cas-config.properties"));
19 | } catch (IOException e) {
20 | throw new RuntimeException("load config error", e);
21 | }
22 | }
23 |
24 | public static String getConfig(String key) {
25 | return properties.getProperty(key);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/CasAndroidClient/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in D:\AndroidSDK/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/CasAndroidClient/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 24
5 | buildToolsVersion "24.0.2"
6 |
7 | defaultConfig {
8 | applicationId "com.casandroidclient"
9 | minSdkVersion 19
10 | targetSdkVersion 24
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile fileTree(dir: 'libs', include: ['*.jar'])
24 | testCompile 'junit:junit:4.12'
25 | compile 'com.android.support:appcompat-v7:24.2.0'
26 | }
27 |
--------------------------------------------------------------------------------
/cas/src/main/java/cas/mapping/UserMapping.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | name, passwd
11 |
12 |
18 |
--------------------------------------------------------------------------------
/cas/src/main/java/cas/mq/message/Message.java:
--------------------------------------------------------------------------------
1 | package cas.mq.message;
2 |
3 | import java.io.Serializable;
4 |
5 | import org.slf4j.Logger;
6 | import org.slf4j.LoggerFactory;
7 |
8 | /**
9 | * 消息实体,存放消息数据
10 | *
11 | * @author ChengPan
12 | */
13 | public class Message implements Serializable{
14 |
15 | private static final long serialVersionUID = 8073211549142445560L;
16 |
17 | protected final Logger logger = LoggerFactory.getLogger(getClass());
18 |
19 | private String content;
20 |
21 | public Message() {}
22 |
23 | public Message(String content) {
24 | this.content = content;
25 | }
26 |
27 | public String getContent() {
28 | return content;
29 | }
30 |
31 | public void setContent(String content) {
32 | this.content = content;
33 | }
34 |
35 | }
36 |
--------------------------------------------------------------------------------
/cas/src/main/java/cas/models/User.java:
--------------------------------------------------------------------------------
1 | package cas.models;
2 |
3 | import java.io.Serializable;
4 |
5 | public class User implements Serializable{
6 | private static final long serialVersionUID = 1L;
7 | private String name;
8 | private String passwd;
9 |
10 | public User() {}
11 |
12 | public User(String name, String passwd) {
13 | super();
14 | this.name = name;
15 | this.passwd = passwd;
16 | }
17 | public String getName() {
18 | return name;
19 | }
20 | public void setName(String name) {
21 | this.name = name;
22 | }
23 | public String getPasswd() {
24 | return passwd;
25 | }
26 | public void setPasswd(String passwd) {
27 | this.passwd = passwd;
28 | }
29 |
30 | @Override
31 | public String toString() {
32 | return "User [name=" + name + ", passwd=" + passwd + "]";
33 | }
34 |
35 |
36 | }
37 |
--------------------------------------------------------------------------------
/cas/src/main/java/cas/mq/receiver/LogoutMessageReceiver.java:
--------------------------------------------------------------------------------
1 | package cas.mq.receiver;
2 |
3 | import cas.mq.message.LogoutMessage;
4 | import cas.mq.message.Message;
5 | import cas.mq.queue.RedisMessageQueue;
6 | import cas.utils.HttpRequest;
7 |
8 | /**
9 | * 注销消息接收者
10 | *
11 | * @author ChengPan
12 | */
13 | public class LogoutMessageReceiver extends Receiver{
14 |
15 | @Override
16 | public void handleMessage(Message message) {
17 | if (message != null) {
18 | LogoutMessage logoutMsg = new LogoutMessage(message);
19 | if (logoutMsg != null && logoutMsg.getLogoutUrls() != null) {
20 | for (String logoutUrl : logoutMsg.getLogoutUrls()) {
21 | logger.debug("{}:{}注销", logoutMsg.getToken(), logoutUrl);
22 | HttpRequest.sendPost(logoutUrl, "token=" + logoutMsg.getToken(), null);
23 | }
24 | }
25 | }
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/client/src/client/model/User.java:
--------------------------------------------------------------------------------
1 | package client.model;
2 |
3 | import java.io.Serializable;
4 |
5 | public class User implements Serializable{
6 | private static final long serialVersionUID = 1L;
7 | private String name;
8 | private String passwd;
9 |
10 | public User() {
11 |
12 | }
13 |
14 | public User(String name, String passwd) {
15 | super();
16 | this.name = name;
17 | this.passwd = passwd;
18 | }
19 | public String getName() {
20 | return name;
21 | }
22 | public void setName(String name) {
23 | this.name = name;
24 | }
25 | public String getPasswd() {
26 | return passwd;
27 | }
28 | public void setPasswd(String passwd) {
29 | this.passwd = passwd;
30 | }
31 |
32 | @Override
33 | public String toString() {
34 | return "User [name=" + name + ", passwd=" + passwd + "]";
35 | }
36 |
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/cas/src/test/java/cas/test/component/Person.java:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | */
4 | package cas.test.component;
5 |
6 | import java.io.Serializable;
7 |
8 |
9 | public class Person implements Serializable{
10 | private static final long serialVersionUID = 1L;
11 |
12 | private String name;
13 | private int age;
14 |
15 | public Person() {
16 | }
17 |
18 | public Person(String name, int age) {
19 | super();
20 | this.name = name;
21 | this.age = age;
22 | }
23 | public String getName() {
24 | return name;
25 | }
26 | public void setName(String name) {
27 | this.name = name;
28 | }
29 | public int getAge() {
30 | return age;
31 | }
32 | public void setAge(int age) {
33 | this.age = age;
34 | }
35 | @Override
36 | public String toString() {
37 | return "Person [name=" + name + ", age=" + age + "]";
38 | }
39 |
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/cas/src/main/java/cas/mq/queue/RedisMessageQueue.java:
--------------------------------------------------------------------------------
1 | package cas.mq.queue;
2 |
3 | import java.util.List;
4 |
5 | import cas.mq.message.Message;
6 | import cas.utils.JsonUtils;
7 | import cas.utils.RedisUtil;
8 |
9 | /**
10 | * 基于Redis的list数据结构实现的消息队列
11 | *
12 | * @author ChengPan
13 | */
14 | public class RedisMessageQueue extends MessageQueue {
15 |
16 | private final String queueName;
17 |
18 | public RedisMessageQueue(String queueName) {
19 | this.queueName = queueName;
20 | }
21 |
22 | @Override
23 | public void push(Message message) {
24 | RedisUtil.getJedis().lpush(queueName, JsonUtils.toJSONString(message));
25 | }
26 |
27 | @Override
28 | public Message pop() {
29 | //redis阻塞操作队列,获取成功返回2个元素,第一个是list的key,第二个是值
30 | List list = RedisUtil.getJedis().brpop(0, queueName);
31 | return JsonUtils.toBean(list.get(1), Message.class);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/client/src/client/listener/SessionLifecycleListener.java:
--------------------------------------------------------------------------------
1 | package client.listener;
2 |
3 | import javax.servlet.http.HttpSession;
4 | import javax.servlet.http.HttpSessionEvent;
5 | import javax.servlet.http.HttpSessionListener;
6 |
7 | import client.cas.component.LogedSessionManager;
8 |
9 | /**
10 | * 监听session的过期或销毁,从{@link client.cas.component.LogedSessionManager}中移除session
11 | *
12 | * @author ChengPan
13 | */
14 | public class SessionLifecycleListener implements HttpSessionListener{
15 |
16 | @Override
17 | public void sessionCreated(HttpSessionEvent arg0) {
18 |
19 | }
20 |
21 | @Override
22 | public void sessionDestroyed(HttpSessionEvent event) {
23 | HttpSession session = event.getSession();
24 | String token = (String) session.getAttribute("token");
25 | if (token != null) {
26 | LogedSessionManager.detach(token.toString());
27 | }
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/java/com/casandroidclient/component/CustomAlertDialogFactory.java:
--------------------------------------------------------------------------------
1 | package com.casandroidclient.component;
2 |
3 | import android.app.ProgressDialog;
4 | import android.content.Context;
5 | import android.text.TextUtils;
6 |
7 | /**
8 | * @author clarechen 2014-10-28 对话框生成器
9 | */
10 | public class CustomAlertDialogFactory {
11 |
12 | /**
13 | * 创建弹出loading框
14 | *
15 | * @param context
16 | * @param message 提示信息,默认为"请稍候..."
17 | * @param cancelable 是否可退出
18 | * @return
19 | */
20 | public static ProgressDialog createProgressDialog(Context context,
21 | String message, boolean cancelable) {
22 | String msg = TextUtils.isEmpty(message) ? "正在加载..." : message;
23 | LoadingDialog dlg = new LoadingDialog(context, msg);
24 | dlg.setCancelable(cancelable);
25 | return dlg;
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/CasAndroidClient/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/cas/src/main/java/cas/utils/QRCodeUtils.java:
--------------------------------------------------------------------------------
1 | package cas.utils;
2 |
3 | import java.io.IOException;
4 | import java.io.OutputStream;
5 |
6 | import com.google.zxing.BarcodeFormat;
7 | import com.google.zxing.WriterException;
8 | import com.google.zxing.client.j2se.MatrixToImageWriter;
9 | import com.google.zxing.common.BitMatrix;
10 | import com.google.zxing.qrcode.QRCodeWriter;
11 |
12 | public class QRCodeUtils {
13 |
14 | public static void writeQRcodeToStream(String content, OutputStream stream) throws WriterException, IOException {
15 | try {
16 | int width = 500; // 图像宽度
17 | int height = 500; // 图像高度
18 | QRCodeWriter writer = new QRCodeWriter();
19 | BitMatrix m = writer.encode(content, BarcodeFormat.QR_CODE, width,
20 | height);
21 | MatrixToImageWriter.writeToStream(m, "png", stream);
22 | } finally {
23 | if (stream != null) {
24 | stream.flush();
25 | stream.close();
26 | }
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/cas/src/main/resources/table-user.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Navicat MySQL Data Transfer
3 |
4 | Source Server : CP_mysql
5 | Source Server Version : 50540
6 | Source Host : localhost:3306
7 | Source Database : java
8 |
9 | Target Server Type : MYSQL
10 | Target Server Version : 50540
11 | File Encoding : 65001
12 |
13 | Date: 2017-12-09 10:08:20
14 | */
15 |
16 | SET FOREIGN_KEY_CHECKS=0;
17 |
18 | -- ----------------------------
19 | -- Table structure for user
20 | -- ----------------------------
21 | DROP TABLE IF EXISTS `user`;
22 | CREATE TABLE `user` (
23 | `id` int(11) NOT NULL AUTO_INCREMENT,
24 | `name` char(255) DEFAULT NULL,
25 | `passwd` varchar(255) DEFAULT NULL,
26 | PRIMARY KEY (`id`)
27 | ) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf-8;
28 |
29 | -- ----------------------------
30 | -- Records of user
31 | -- ----------------------------
32 | INSERT INTO `user` VALUES ('1', '123', '123');
33 |
--------------------------------------------------------------------------------
/client/src/client/cas/component/LogedSessionManager.java:
--------------------------------------------------------------------------------
1 | package client.cas.component;
2 |
3 | import java.util.Map;
4 | import java.util.concurrent.ConcurrentHashMap;
5 | import javax.servlet.http.HttpSession;
6 |
7 | /**
8 | * 持有已登录的会话session,以便于在session过期,或{@link client.filter.LogoutFilter}收到注销请求时
9 | * 根据session中存储的token,或注销请求传递过来的token,将集合中的session取出,进行销毁
10 | *
11 | * @author ChengPan
12 | */
13 | public class LogedSessionManager {
14 |
15 | private LogedSessionManager() {}
16 |
17 | private static final Map logedSessions = new ConcurrentHashMap<>();
18 |
19 | public static void attach(String token, HttpSession session) {
20 | logedSessions.put(token, session);
21 | }
22 |
23 | public static HttpSession detach(String token) {
24 | return logedSessions.remove(token);
25 | }
26 |
27 | public static HttpSession get(String token) {
28 | if (token == null)
29 | return null;
30 | return logedSessions.get(token);
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/cas/src/main/java/cas/cdao/CacheDao.java:
--------------------------------------------------------------------------------
1 | package cas.cdao;
2 |
3 | import java.util.Enumeration;
4 | import java.util.Map;
5 |
6 | public interface CacheDao {
7 |
8 | Map getAllAttribute(String key);
9 |
10 | void setAllAttributes(String key, Map attributes);
11 |
12 | Object getAttribute(String key, String fieldName);
13 |
14 | void setAttribute(String key, String fieldName, Object value);
15 |
16 | void removeAttribute(String token, String name);
17 |
18 | Enumeration getAttributeNames(String key);
19 |
20 | String[] getValueNames(String key);
21 |
22 | void del(String key);
23 |
24 | void setExpire(String key, int expire);
25 |
26 | Long getExpire(String key);
27 |
28 | /**
29 | * 设置key永不过期
30 | * @param key
31 | */
32 | void setPersist(String key);
33 |
34 | boolean exists(String key);
35 |
36 | void setWithExpire(String key, Object value, int expire);
37 |
38 | Object get(String key);
39 | }
40 |
--------------------------------------------------------------------------------
/cas/src/main/java/cas/cdao/factory/CacheDaoFactory.java:
--------------------------------------------------------------------------------
1 | package cas.cdao.factory;
2 |
3 | import cas.cdao.CacheDao;
4 | import cas.support.ConfigLoader;
5 |
6 | /**
7 | * 根据{@link cas.support.ConfigLoader}获取CacheDao实现类配置,实例化CacheDao
8 | *
9 | * @author ChengPan
10 | */
11 | public class CacheDaoFactory {
12 | private CacheDaoFactory() {}
13 |
14 | private static final Class> clazz;
15 |
16 | private static final String CACHE_DAO_IMPL_CLASS_KEY = "cache.dao.impl.class";
17 |
18 | static {
19 | try {
20 | clazz = Class
21 | .forName(ConfigLoader.getConfig(CACHE_DAO_IMPL_CLASS_KEY));
22 | }
23 | catch (ClassNotFoundException e) {
24 | throw new RuntimeException("can not found CacheDao class", e);
25 | }
26 | }
27 |
28 | public static CacheDao newCacheDaoInstance() {
29 | try {
30 | return (CacheDao) clazz.newInstance();
31 | }
32 | catch (InstantiationException e) {
33 | throw new RuntimeException(e);
34 | }
35 | catch (IllegalAccessException e) {
36 | throw new RuntimeException(e);
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/cas/src/test/java/cas/test/service/UserServiceTest.java:
--------------------------------------------------------------------------------
1 | package cas.test.service;
2 |
3 | import java.lang.reflect.Method;
4 |
5 | import org.junit.Test;
6 | import org.junit.runner.RunWith;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.test.context.ContextConfiguration;
9 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
10 |
11 | import cas.models.User;
12 | import cas.service.UserService;
13 |
14 | @RunWith(SpringJUnit4ClassRunner.class)
15 | @ContextConfiguration({"classpath:spring-mybatis.xml"})
16 | public class UserServiceTest {
17 |
18 | @Autowired
19 | private UserService userService;
20 |
21 | @Test
22 | public void testGetUser(){
23 | System.out.println(userService.verifyUserLogin(new User("cp", "123")));
24 | }
25 |
26 | @Test
27 | public void testProxyObject(){
28 | System.out.println(userService);
29 | Method[] methods = userService.getClass().getMethods();
30 | for(Method m : methods){
31 | System.out.println(m.getName());
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/cas/src/main/resources/logback.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | cas
4 |
5 |
6 |
7 |
8 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
9 |
10 |
11 |
12 |
13 | ${logDir}/cas_current.log
14 |
15 | ${logDir}/cas_%d{yyyy-MM-dd}.log.zip
16 |
17 |
18 | %d{yyyy-MM-dd HH:mm:ss}[%-5level][%thread]%logger{36} - %msg%n
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/layout/progress_loding_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
18 |
19 |
28 |
29 |
--------------------------------------------------------------------------------
/client/WebRoot/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | client
4 |
5 | index.jsp
6 |
7 |
8 |
9 | client.listener.SessionLifecycleListener
10 |
11 |
12 |
13 | logoutFilter
14 | client.filter.LogoutFilter
15 |
16 |
17 | logoutFilter
18 | /logout
19 |
20 |
21 |
22 | authenticationFilter
23 | client.filter.AuthenticationFilter
24 |
25 |
26 | authenticationFilter
27 | /*
28 |
29 |
--------------------------------------------------------------------------------
/cas/src/main/java/cas/controller/PublicController.java:
--------------------------------------------------------------------------------
1 | package cas.controller;
2 |
3 | import java.io.IOException;
4 |
5 | import javax.servlet.http.HttpServletRequest;
6 | import javax.servlet.http.HttpServletResponse;
7 | import javax.servlet.http.HttpSession;
8 |
9 | import org.springframework.stereotype.Controller;
10 | import org.springframework.web.bind.annotation.RequestMapping;
11 |
12 | import cas.utils.QRCodeUtils;
13 |
14 | import com.alibaba.fastjson.JSONObject;
15 | import com.google.zxing.WriterException;
16 |
17 | @Controller
18 | @RequestMapping("/public")
19 | public class PublicController {
20 |
21 | /**
22 | * 生成带有会话id的二维码供客户端登录
23 | * @param response
24 | * @param request
25 | * @param session
26 | * @throws WriterException
27 | * @throws IOException
28 | */
29 | @RequestMapping("loginQRCode")
30 | public void loginQRCode(HttpServletResponse response, HttpServletRequest request,
31 | HttpSession session) throws WriterException, IOException {
32 | JSONObject json = new JSONObject();
33 | json.put("sessionid", session.getId());
34 | QRCodeUtils.writeQRcodeToStream(json.toJSONString(), response.getOutputStream());
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
14 |
20 | />
21 |
26 |
27 |
--------------------------------------------------------------------------------
/client/src/client/filter/LogoutFilter.java:
--------------------------------------------------------------------------------
1 | package client.filter;
2 |
3 | import java.io.IOException;
4 |
5 | import javax.servlet.Filter;
6 | import javax.servlet.FilterChain;
7 | import javax.servlet.FilterConfig;
8 | import javax.servlet.ServletException;
9 | import javax.servlet.ServletRequest;
10 | import javax.servlet.ServletResponse;
11 | import javax.servlet.http.HttpServletRequest;
12 | import javax.servlet.http.HttpSession;
13 |
14 | import client.cas.component.LogedSessionManager;
15 |
16 | /**
17 | * 接收服务器的注销请求
18 | * @author ChengPan
19 | */
20 | public class LogoutFilter implements Filter{
21 |
22 | @Override
23 | public void destroy() {
24 |
25 | }
26 |
27 | @Override
28 | public void doFilter(ServletRequest req, ServletResponse resp,
29 | FilterChain arg2) throws IOException, ServletException {
30 | HttpServletRequest request = (HttpServletRequest) req;
31 | String token = request.getParameter("token");
32 | HttpSession session = LogedSessionManager.get(token);
33 | if (session != null) {
34 | session.invalidate();
35 | }
36 | }
37 |
38 | @Override
39 | public void init(FilterConfig arg0) throws ServletException {
40 |
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/cas/src/test/java/cas/test/component/BufferedCacheHttpSessionTest.java:
--------------------------------------------------------------------------------
1 | package cas.test.component;
2 |
3 | import java.util.Arrays;
4 |
5 | import org.junit.Test;
6 |
7 | import cas.custom.component.session.BufferedCacheHttpSession;
8 |
9 | public class BufferedCacheHttpSessionTest {
10 |
11 | @Test
12 | public void testGetAndSetVal(){
13 | BufferedCacheHttpSession session = new BufferedCacheHttpSession(null, "token");
14 | Person p = new Person("程攀",123);
15 | session.setAttribute("userInfo", p);
16 | session.setMaxInactiveInterval(200);
17 | System.out.println(session.getAttribute("userInfo").toString());
18 | session.commit();
19 |
20 | BufferedCacheHttpSession session2 = new BufferedCacheHttpSession(null, "token");
21 | Person get = (Person) session2.getAttribute("userInfo");
22 | System.out.println(get.getName());
23 | }
24 |
25 | @Test
26 | public void testGetValueNames(){
27 | BufferedCacheHttpSession session = new BufferedCacheHttpSession(null, "token");
28 | Person p = new Person("程攀",123);
29 | session.setAttribute("userInfo", p);
30 | session.commit();
31 |
32 | BufferedCacheHttpSession session2 = new BufferedCacheHttpSession(null, "token");
33 | System.out.println(Arrays.asList(session2.getValueNames()));
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/java/com/casandroidclient/component/DecodeFormatManager.java:
--------------------------------------------------------------------------------
1 | package com.casandroidclient.component;
2 |
3 | import com.google.zxing.BarcodeFormat;
4 |
5 | import java.util.Collection;
6 | import java.util.EnumSet;
7 | import java.util.Set;
8 |
9 | public class DecodeFormatManager {
10 |
11 | // 1D解码
12 | private static final Set PRODUCT_FORMATS;
13 | private static final Set INDUSTRIAL_FORMATS;
14 | private static final Set ONE_D_FORMATS;
15 |
16 | // 二维码解码
17 | private static final Set QR_CODE_FORMATS;
18 |
19 | static {
20 | PRODUCT_FORMATS = EnumSet.of(BarcodeFormat.UPC_A, BarcodeFormat.UPC_E, BarcodeFormat.EAN_13, BarcodeFormat.EAN_8, BarcodeFormat.RSS_14, BarcodeFormat.RSS_EXPANDED);
21 | INDUSTRIAL_FORMATS = EnumSet.of(BarcodeFormat.CODE_39, BarcodeFormat.CODE_93, BarcodeFormat.CODE_128, BarcodeFormat.ITF, BarcodeFormat.CODABAR);
22 | ONE_D_FORMATS = EnumSet.copyOf(PRODUCT_FORMATS);
23 | ONE_D_FORMATS.addAll(INDUSTRIAL_FORMATS);
24 |
25 | QR_CODE_FORMATS = EnumSet.of(BarcodeFormat.QR_CODE);
26 | }
27 |
28 | public static Collection getQrCodeFormats() {
29 | return QR_CODE_FORMATS;
30 | }
31 |
32 | public static Collection getBarCodeFormats() {
33 | return ONE_D_FORMATS;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/cas/src/main/java/cas/filter/LoginInterceptor.java:
--------------------------------------------------------------------------------
1 | package cas.filter;
2 |
3 | import javax.servlet.http.HttpServletRequest;
4 | import javax.servlet.http.HttpServletResponse;
5 | import javax.servlet.http.HttpSession;
6 |
7 | import org.springframework.web.servlet.HandlerInterceptor;
8 | import org.springframework.web.servlet.ModelAndView;
9 |
10 | /**
11 | * 登录拦截器
12 | * @author ChengPan
13 | */
14 | public class LoginInterceptor implements HandlerInterceptor{
15 |
16 | public void afterCompletion(HttpServletRequest request,
17 | HttpServletResponse response, Object handler, Exception exc)
18 | throws Exception {
19 |
20 | }
21 |
22 | public void postHandle(HttpServletRequest request, HttpServletResponse response,
23 | Object handler, ModelAndView modelAndView) throws Exception {
24 | }
25 |
26 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
27 | Object handler) throws Exception {
28 | HttpSession session = request.getSession();
29 | Object user = session.getAttribute("user");
30 | if(user != null){
31 | return true;
32 | }
33 | response.sendRedirect(request.getContextPath() + "/login");
34 | return false;
35 | }
36 |
37 | }
--------------------------------------------------------------------------------
/cas/src/main/resources/spring-component.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/java/com/casandroidclient/component/LoadingDialog.java:
--------------------------------------------------------------------------------
1 | package com.casandroidclient.component;
2 |
3 | import android.app.ProgressDialog;
4 | import android.content.Context;
5 | import android.os.Bundle;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.widget.TextView;
9 | import com.casandroidclient.R;
10 |
11 |
12 | public class LoadingDialog extends ProgressDialog {
13 |
14 | private Context mContext;
15 | private String msg;
16 | private TextView content;
17 |
18 | public LoadingDialog(Context context, String message) {
19 | super(context, R.style.Theme_dialog);
20 | this.mContext = context;
21 | this.msg = message;
22 | }
23 |
24 | @Override
25 | protected void onCreate(Bundle savedInstanceState) {
26 | super.onCreate(savedInstanceState);
27 |
28 | LayoutInflater inflater = (LayoutInflater) mContext
29 | .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
30 | View contentView = inflater.inflate(R.layout.progress_loding_layout,
31 | null);
32 | content = (TextView) contentView.findViewById(R.id.content);
33 | content.setText(msg);
34 | setCanceledOnTouchOutside(false);
35 | setContentView(contentView);
36 | }
37 |
38 | public void setMessage(CharSequence c) {
39 | content.setText(c);
40 | }
41 |
42 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 2018-03-26
2 | 更新见https://github.com/nameof/ex-session-sso
3 |
4 | ----------------------
5 |
6 | # redis-session
7 | 默认基于redis封装自定义HttpSession(不仅局限于redis,提供了接口,可以扩展CacheDao将Session数据托管到各种缓存,memcached、mongodb、ehcache),实现全局Session共享,提取出Session的好处是显而易见的,会话数据不再是一个黑盒,我们可以对Session进行监控和自由访问,例如集成WebSocket,实现跨域单点登录,本repo还提供支持android客户端扫码登陆,并使用redis模拟消息队列进行注销消息的发送。
8 |
9 | 实现思路与[spring-session](http://projects.spring.io/spring-session/)一致,也存在同样的缺陷,例如丧失了HttpSession相关Listener的处理能力。
10 |
11 | ----------------------
12 |
13 | # 使用
14 | 启动cas服务器端前需开启连接redis,默认是连接本地的6379端口的redis 。
15 |
16 | ----------------------
17 |
18 | # 说明
19 | 整体逻辑是cas认证中心作为全局登录和注销控制中心,通过servlet拦截器将默认的HttpSession替换为缓存实现(默认使用redis)的Session,达到会话统一控制。
20 |
21 | 附带的一个简易客户端站点的实现是仍然使用局部Session,登陆时通过重定向到cas进行统一登录,登录成功cas则携带token返回到客户端站点,客户端确认token后,cas将用户会话数据发送给客户端站点,客户端站点再将其存储到局部会话中;
22 |
23 | 注销过程类似,定向到cas注销,完成后cas销毁全局会话,并通过redis消息队列通知各个客户端站点销毁局部会话。
24 |
25 | 整个认证过程可以看作实现了简易的[CAS协议](https://apereo.github.io/cas/4.2.x/protocol/CAS-Protocol.html)。
26 |
27 | 如果要实现客户端和服务器站点真正的所有Session会话数据全局统一共享和管理,那么可以将cas的缓存Session涉及到的API打包到客户端,客户端采用同样的方式去访问会话数据。此处没有提供实现,大家可以自己尝试,或者后面有时间会提供实现案例=_= 。
28 |
29 | 扫码登录采用轮询实现,可延伸方案有websocket。
30 |
31 |
32 | ----------------------
33 | # TODO
34 | - Session的相关Listener的实现
35 | - Servlet API中LastAccessedTime的实现
36 | - 服务器客户端的安全通信
37 | - token等各种安全机制
38 | - 代码DEBUG和设计优化
39 | - 功能扩充
40 |
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/java/com/casandroidclient/component/PreviewCallback.java:
--------------------------------------------------------------------------------
1 | package com.casandroidclient.component;
2 |
3 | import android.graphics.Point;
4 | import android.hardware.Camera;
5 | import android.os.Handler;
6 | import android.os.Message;
7 | import android.util.Log;
8 |
9 | public class PreviewCallback implements Camera.PreviewCallback {
10 |
11 | private static final String TAG = PreviewCallback.class.getSimpleName();
12 |
13 | private final CameraConfigurationManager configManager;
14 | private Handler previewHandler;
15 | private int previewMessage;
16 |
17 | public PreviewCallback(CameraConfigurationManager configManager) {
18 | this.configManager = configManager;
19 | }
20 |
21 | public void setHandler(Handler previewHandler, int previewMessage) {
22 | this.previewHandler = previewHandler;
23 | this.previewMessage = previewMessage;
24 | }
25 |
26 | @Override
27 | public void onPreviewFrame(byte[] data, Camera camera) {
28 | Point cameraResolution = configManager.getCameraResolution();
29 | Handler thePreviewHandler = previewHandler;
30 | if (cameraResolution != null && thePreviewHandler != null) {
31 | Message message = thePreviewHandler.obtainMessage(previewMessage, cameraResolution.x, cameraResolution.y, data);
32 | message.sendToTarget();
33 | previewHandler = null;
34 | } else {
35 | Log.d(TAG, "Got preview callback, but no handler or resolution available");
36 | }
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/cas/src/main/java/cas/custom/component/factory/CacheHttpSessionFactory.java:
--------------------------------------------------------------------------------
1 | package cas.custom.component.factory;
2 |
3 | import java.lang.reflect.Constructor;
4 |
5 | import javax.servlet.http.HttpSession;
6 |
7 | import cas.custom.component.session.HttpSessionWrapper;
8 | import cas.support.ConfigLoader;
9 |
10 | /**
11 | * 根据{@link cas.support.ConfigLoader}获取自定义HttpSession实现类配置,实例化自定义HttpSession
12 | * @author ChengPan
13 | */
14 | public class CacheHttpSessionFactory {
15 |
16 | private CacheHttpSessionFactory() {}
17 |
18 | private static final Class> clazz;
19 |
20 | private static final String SESSION_IMPL_CLASS_KEY = "cache.httpsession.impl.class";
21 |
22 | static {
23 | try {
24 | clazz = Class
25 | .forName(ConfigLoader.getConfig(SESSION_IMPL_CLASS_KEY));
26 | }
27 | catch (ClassNotFoundException e) {
28 | throw new RuntimeException("can not found session class", e);
29 | }
30 | }
31 |
32 | public static HttpSessionWrapper newSessionInstance(HttpSession session, String token) {
33 | Constructor> constructor = null;
34 | try {
35 | constructor = clazz.getConstructor(HttpSession.class, String.class);
36 | return (HttpSessionWrapper) constructor.newInstance(session, token);
37 | }
38 | catch (NoSuchMethodException e) {
39 | throw new RuntimeException(e);
40 | }
41 | catch (Exception e) {
42 | throw new RuntimeException(e);
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/cas/src/main/webapp/WEB-INF/views/login.jsp:
--------------------------------------------------------------------------------
1 | <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
2 |
3 |
4 |
5 |
6 | 登录
7 |
8 |
20 |
21 |
22 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/cas/src/main/java/cas/filter/AuthenticationFilter.java:
--------------------------------------------------------------------------------
1 | package cas.filter;
2 |
3 | import java.io.IOException;
4 |
5 | import javax.servlet.Filter;
6 | import javax.servlet.FilterChain;
7 | import javax.servlet.FilterConfig;
8 | import javax.servlet.ServletException;
9 | import javax.servlet.ServletRequest;
10 | import javax.servlet.ServletResponse;
11 | import javax.servlet.http.HttpServletRequest;
12 | import javax.servlet.http.HttpServletResponse;
13 | import javax.servlet.http.HttpSession;
14 |
15 | import org.apache.commons.lang.StringUtils;
16 |
17 | import cas.custom.component.factory.CacheHttpSessionFactory;
18 | import cas.models.User;
19 | import cas.utils.JsonUtils;
20 | /**
21 | * 接收CAS客户端站点的token验证请求,成功返回JSON格式用户信息
22 | * @author ChengPan
23 | */
24 | public class AuthenticationFilter implements Filter{
25 |
26 | @Override
27 | public void init(FilterConfig filterConfig) throws ServletException {
28 |
29 | }
30 |
31 | @Override
32 | public void doFilter(ServletRequest request, ServletResponse response,
33 | FilterChain chain) throws IOException, ServletException {
34 | HttpServletRequest req = (HttpServletRequest)request;
35 | HttpServletResponse resp = (HttpServletResponse)response;
36 | String token = req.getParameter("token");
37 | if (StringUtils.isNotBlank(token)) {
38 | HttpSession session = CacheHttpSessionFactory.newSessionInstance(req.getSession(), token);
39 | User user = (User) session.getAttribute("user");
40 | if (user != null) {
41 | resp.getWriter().write(JsonUtils.toJSONString(user));
42 | }
43 | }
44 | }
45 |
46 | @Override
47 | public void destroy() {
48 |
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/cas/src/main/java/cas/filter/CacheSessionFilter.java:
--------------------------------------------------------------------------------
1 | package cas.filter;
2 |
3 | import java.io.IOException;
4 |
5 | import javax.servlet.Filter;
6 | import javax.servlet.FilterChain;
7 | import javax.servlet.FilterConfig;
8 | import javax.servlet.ServletException;
9 | import javax.servlet.ServletRequest;
10 | import javax.servlet.ServletResponse;
11 | import javax.servlet.http.HttpServletRequest;
12 | import javax.servlet.http.HttpServletResponse;
13 |
14 | import cas.custom.component.request.CustomHttpServletRequest;
15 | import cas.custom.component.session.CustomSessionProcessor;
16 | import cas.utils.RedisUtil;
17 |
18 | /**
19 | * 处理请求之前,对HttpServletRequest包装类的实例化
20 | * 请求完成之后,提交自定义Session数据到缓存中,并释放缓存连接资源
21 | * @author ChengPan
22 | */
23 | public class CacheSessionFilter implements Filter{
24 |
25 | @Override
26 | public void destroy() {
27 |
28 | }
29 |
30 | @Override
31 | public void doFilter(ServletRequest request, ServletResponse response,
32 | FilterChain chain) throws IOException, ServletException {
33 | HttpServletRequest req = (HttpServletRequest)request;
34 | HttpServletResponse resp = (HttpServletResponse)response;
35 | CustomHttpServletRequest wrapper = new CustomHttpServletRequest(req, resp);
36 | try {
37 | chain.doFilter(wrapper, response);
38 | } finally {
39 | if (wrapper.getSession(false) instanceof CustomSessionProcessor) {
40 | ((CustomSessionProcessor) wrapper.getSession()).commit();
41 | }
42 | RedisUtil.returnResource();//release redis
43 | }
44 | }
45 |
46 | @Override
47 | public void init(FilterConfig arg0) throws ServletException {
48 |
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/cas/src/main/java/cas/utils/CookieUtil.java:
--------------------------------------------------------------------------------
1 | package cas.utils;
2 |
3 | import javax.servlet.http.Cookie;
4 | import javax.servlet.http.HttpServletRequest;
5 | import javax.servlet.http.HttpServletResponse;
6 |
7 | public class CookieUtil {
8 | private CookieUtil() {}
9 |
10 | public static void addCookie(HttpServletResponse response, String name, String value, int maxAge) {
11 | Cookie cookie = new Cookie(name, value);
12 | cookie.setMaxAge(maxAge);
13 | response.addCookie(cookie);
14 | }
15 |
16 | public static void addCookie(HttpServletResponse response, String name, String value) {
17 | Cookie cookie = new Cookie(name, value);
18 | response.addCookie(cookie);
19 | }
20 |
21 | public static void removeCookie(HttpServletResponse response, String name) {
22 | Cookie uid = new Cookie(name, null);
23 | uid.setMaxAge(0);
24 | response.addCookie(uid);
25 | }
26 |
27 | public static String getCookieValue(HttpServletRequest request,String cookieName) {
28 | Cookie[] cookies = request.getCookies();
29 | if (cookies != null) {
30 | for (Cookie cookie : cookies) {
31 | if (cookie.getName().equals(cookieName)) {
32 | return cookie.getValue();
33 | }
34 | }
35 | }
36 | return null;
37 | }
38 |
39 | public static Cookie getCookie(HttpServletRequest request,String cookieName) {
40 | Cookie[] cookies = request.getCookies();
41 | if (cookies != null) {
42 | for (Cookie cookie : cookies) {
43 | if (cookie.getName().equals(cookieName)) {
44 | return cookie;
45 | }
46 | }
47 | }
48 | return null;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/java/com/casandroidclient/LoginActivity.java:
--------------------------------------------------------------------------------
1 | package com.casandroidclient;
2 |
3 | import android.content.Intent;
4 | import android.content.SharedPreferences;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.os.Bundle;
7 | import android.view.View;
8 | import android.widget.Button;
9 | import android.widget.EditText;
10 | import android.widget.Toast;
11 |
12 | public class LoginActivity extends AppCompatActivity {
13 |
14 | private EditText userName;
15 | private EditText password;
16 | private Button login;
17 | @Override
18 | protected void onCreate(Bundle savedInstanceState) {
19 | super.onCreate(savedInstanceState);
20 | setContentView(R.layout.activity_login);
21 | userName = (EditText) findViewById(R.id.userName);
22 | password = (EditText) findViewById(R.id.password);
23 | login = (Button) findViewById(R.id.login);
24 | login.setOnClickListener(new View.OnClickListener() {
25 | @Override
26 | public void onClick(View v) {
27 | String name = userName.getText().toString().trim();
28 | String passwd = password.getText().toString().trim();
29 | if (!"".equals(name) && !"".equals(passwd)) {
30 | Intent intent = new Intent(LoginActivity.this, MainActivity.class);
31 | Bundle bundle = new Bundle();
32 | bundle.putString("username", name);
33 | bundle.putString("password", name);
34 | intent.putExtras(bundle);
35 | startActivity(intent);
36 | finish();
37 | } else {
38 | Toast.makeText(LoginActivity.this, "用户名和密码不能为空!", Toast.LENGTH_LONG).show();
39 | }
40 | }
41 | });
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/cas/src/main/java/cas/utils/RedisUtil.java:
--------------------------------------------------------------------------------
1 | package cas.utils;
2 |
3 | import redis.clients.jedis.Jedis;
4 | import redis.clients.jedis.JedisPool;
5 | import redis.clients.jedis.JedisPoolConfig;
6 |
7 | public final class RedisUtil {
8 |
9 | private static String ADDR = "127.0.0.1";
10 |
11 | private static int PORT = 6379;
12 |
13 | private static int MAX_ACTIVE = 1024;
14 |
15 | private static int MAX_IDLE = 200;
16 |
17 | private static int TIMEOUT = 10000;
18 |
19 | private static boolean TEST_ON_BORROW = true;
20 |
21 | private static JedisPool jedisPool = null;
22 |
23 | private static ThreadLocal threadLocal = new ThreadLocal();
24 |
25 | static {
26 | try {
27 | JedisPoolConfig config = new JedisPoolConfig();
28 | config.setMaxIdle(MAX_ACTIVE);
29 | config.setMaxIdle(MAX_IDLE);
30 | config.setTestOnBorrow(TEST_ON_BORROW);
31 | jedisPool = new JedisPool(config, ADDR, PORT, TIMEOUT);
32 | }
33 | catch (Exception e) {
34 | throw new IllegalStateException("failed to init jedis pool",e);
35 | }
36 | }
37 |
38 | public static Jedis getJedis() {
39 | Jedis resource = null;
40 | try {
41 | resource = threadLocal.get();
42 | if(resource != null){
43 | return resource;
44 | }
45 | resource = jedisPool.getResource();
46 | threadLocal.set(resource);
47 | return resource;
48 | }
49 | catch (Exception e) {
50 | throw new IllegalStateException("failed to get JedisResource from pool",e);
51 | }
52 | }
53 |
54 | public static void returnResource() {
55 | Jedis jedis = threadLocal.get();
56 | if (jedis != null) {
57 | threadLocal.remove();
58 | jedis.close();
59 | }
60 | }
61 | }
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/java/com/casandroidclient/component/OpenCameraInterface.java:
--------------------------------------------------------------------------------
1 | package com.casandroidclient.component;
2 |
3 | import android.hardware.Camera;
4 | import android.util.Log;
5 |
6 | public class OpenCameraInterface {
7 |
8 | private static final String TAG = OpenCameraInterface.class.getName();
9 |
10 | /**
11 | * Opens the requested camera with {@link Camera#open(int)}, if one exists.
12 | *
13 | * @param cameraId
14 | * camera ID of the camera to use. A negative value means
15 | * "no preference"
16 | * @return handle to {@link Camera} that was opened
17 | */
18 | public static Camera open(int cameraId) {
19 |
20 | int numCameras = Camera.getNumberOfCameras();
21 | if (numCameras == 0) {
22 | Log.w(TAG, "No cameras!");
23 | return null;
24 | }
25 |
26 | boolean explicitRequest = cameraId >= 0;
27 |
28 | if (!explicitRequest) {
29 | // Select a camera if no explicit camera requested
30 | int index = 0;
31 | while (index < numCameras) {
32 | Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
33 | Camera.getCameraInfo(index, cameraInfo);
34 | if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
35 | break;
36 | }
37 | index++;
38 | }
39 |
40 | cameraId = index;
41 | }
42 |
43 | Camera camera;
44 | if (cameraId < numCameras) {
45 | Log.i(TAG, "Opening camera #" + cameraId);
46 | camera = Camera.open(cameraId);
47 | } else {
48 | if (explicitRequest) {
49 | Log.w(TAG, "Requested camera does not exist: " + cameraId);
50 | camera = null;
51 | } else {
52 | Log.i(TAG, "No camera facing back; returning camera #0");
53 | camera = Camera.open(0);
54 | }
55 | }
56 |
57 | return camera;
58 | }
59 |
60 | /**
61 | * Opens a rear-facing camera with {@link Camera#open(int)}, if one exists,
62 | * or opens camera 0.
63 | *
64 | * @return handle to {@link Camera} that was opened
65 | */
66 | public static Camera open() {
67 | return open(-1);
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/cas/src/main/java/cas/custom/component/request/CustomHttpServletRequest.java:
--------------------------------------------------------------------------------
1 | package cas.custom.component.request;
2 |
3 | import java.util.UUID;
4 |
5 | import javax.servlet.http.HttpServletRequest;
6 | import javax.servlet.http.HttpServletRequestWrapper;
7 | import javax.servlet.http.HttpServletResponse;
8 | import javax.servlet.http.HttpSession;
9 |
10 | import org.apache.commons.lang.StringUtils;
11 |
12 | import cas.custom.component.factory.CacheHttpSessionFactory;
13 | import cas.custom.component.session.HttpSessionWrapper;
14 | import cas.utils.CookieUtil;
15 |
16 | /**
17 | * HttpServletRequest的包装类,用于包装获取和创建HttpSession操作
18 | *
19 | * @author ChengPan
20 | */
21 | public class CustomHttpServletRequest extends HttpServletRequestWrapper {
22 |
23 | private HttpSession session;
24 |
25 | private HttpServletResponse response;
26 |
27 | public static final String COOKIE_SESSION_KEY = "token";
28 |
29 | private boolean isNewSession = false;
30 |
31 | public CustomHttpServletRequest(HttpServletRequest request, HttpServletResponse response) {
32 | super(request);
33 | this.response = response;
34 | }
35 |
36 | @Override
37 | public HttpSession getSession(boolean create) {
38 | if (session != null) {
39 | return session;
40 | }
41 | if (!create) {
42 | return null;
43 | }
44 | String token = CookieUtil.getCookieValue(this, COOKIE_SESSION_KEY);
45 | if (StringUtils.isBlank(token)) {
46 | isNewSession = true;
47 | token = UUID.randomUUID().toString();
48 | CookieUtil.addCookie(response, COOKIE_SESSION_KEY, token);
49 | }
50 | HttpSessionWrapper session = CacheHttpSessionFactory.newSessionInstance(super.getSession(), token);
51 | session.setNew(isNewSession);
52 |
53 | this.session = session;
54 | return session;
55 | }
56 |
57 | @Override
58 | public HttpSession getSession() {
59 | return this.getSession(true);
60 | }
61 | }
--------------------------------------------------------------------------------
/cas/src/main/java/cas/mq/message/LogoutMessage.java:
--------------------------------------------------------------------------------
1 | package cas.mq.message;
2 |
3 | import java.util.List;
4 |
5 | import cas.utils.JsonUtils;
6 |
7 | /**
8 | * 注销消息
9 | * @author ChengPan
10 | */
11 | public class LogoutMessage extends Message{
12 |
13 | private static final long serialVersionUID = 1923709448488814904L;
14 |
15 | private InnerMessage logoutMessage;
16 |
17 | public LogoutMessage() {}
18 |
19 | public LogoutMessage(Message message) {
20 | this(message.getContent());
21 | }
22 |
23 | public LogoutMessage(String content) {
24 | super(content);
25 | logoutMessage = JsonUtils.toBean(content, InnerMessage.class);
26 | }
27 |
28 | public LogoutMessage(String token, List logoutUrls) {
29 | logoutMessage = new InnerMessage(token, logoutUrls);
30 | refreshContent();
31 | }
32 |
33 | public String getToken() {
34 | return logoutMessage.getToken();
35 | }
36 |
37 | public List getLogoutUrls() {
38 | return logoutMessage.getLogoutUrls();
39 | }
40 |
41 | public void setToken(String token) {
42 | logoutMessage.setToken(token);
43 | refreshContent();
44 | }
45 |
46 | public void setLogoutUrls(List logoutUrls) {
47 | logoutMessage.setLogoutUrls(logoutUrls);
48 | refreshContent();
49 | }
50 |
51 | private void refreshContent() {
52 | setContent(JsonUtils.toJSONString(logoutMessage));
53 | }
54 |
55 | public static class InnerMessage {
56 |
57 | private String token;
58 |
59 | private List logoutUrls;
60 |
61 | public InnerMessage() {}
62 |
63 | public InnerMessage(String token, List logoutUrls) {
64 | setToken(token);
65 | setLogoutUrls(logoutUrls);
66 | }
67 |
68 | public String getToken() {
69 | return token;
70 | }
71 |
72 | public void setToken(String token) {
73 | this.token = token;
74 | }
75 |
76 | public List getLogoutUrls() {
77 | return logoutUrls;
78 | }
79 |
80 | public void setLogoutUrls(List logoutUrls) {
81 | this.logoutUrls = logoutUrls;
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/java/com/casandroidclient/utils/SharedPreferenceUtils.java:
--------------------------------------------------------------------------------
1 | package com.casandroidclient.utils;
2 |
3 | import android.content.Context;
4 | import android.content.SharedPreferences;
5 |
6 | /**
7 | * Created by kenderson on 2015/3/19.
8 | */
9 | public class SharedPreferenceUtils {
10 | private static SharedPreferences settings;
11 | private static SharedPreferences.Editor editor;
12 |
13 | public static void initSharedPreference(Context context) {
14 | settings = context.getSharedPreferences("StoreManager", context.MODE_PRIVATE);
15 | editor = settings.edit();
16 | }
17 |
18 | public static void putBoolean(String key, Boolean value) {
19 | editor.putBoolean(key, value);
20 | editor.commit();
21 | }
22 |
23 | public static void putInt(String key, int value) {
24 |
25 | editor.putInt(key, value);
26 | editor.commit();
27 | }
28 |
29 | public static void putFloat(String key, float value) {
30 | editor.putFloat(key, value);
31 | editor.commit();
32 | }
33 |
34 | public static void putString(String key, String value) {
35 | editor.putString(key, value);
36 | editor.commit();
37 | }
38 |
39 | public static void putLong(String key, long value) {
40 | editor.putLong(key, value);
41 | editor.commit();
42 | }
43 |
44 |
45 | /**
46 | * @param key the key to use for get the value
47 | * @param def if can not get the value then return the a default value
48 | * @return
49 | */
50 | public static String getString(String key, String def) {
51 | return settings.getString(key, def);
52 | }
53 |
54 | public static int getInt(String key, int def) {
55 | return settings.getInt(key, def);
56 | }
57 |
58 | public static float getFloat(String key, float def) {
59 | return settings.getFloat(key, def);
60 | }
61 |
62 | public static boolean getBoolean(String key, boolean def) {
63 | return settings.getBoolean(key, def);
64 | }
65 |
66 | public static long getLong(String key, long def) {
67 | return settings.getLong(key, def);
68 | }
69 |
70 |
71 | }
72 |
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/java/com/casandroidclient/utils/HttpRequest.java:
--------------------------------------------------------------------------------
1 | package com.casandroidclient.utils;
2 |
3 | import java.io.*;
4 | import java.net.*;
5 | import java.util.Map;
6 |
7 | import android.R.integer;
8 | import android.R.string;
9 | import android.graphics.Bitmap;
10 | import android.graphics.BitmapFactory;
11 | import android.os.Handler;
12 | import android.os.Message;
13 | import android.util.Log;
14 | import android.widget.ImageView;
15 |
16 | public class HttpRequest {
17 |
18 | public static String SERVER = "http://192.168.7.157:8080/cas/processQRCodeLogin";
19 |
20 | public static String httpPost(String url, String params, Map cookies) throws IOException {
21 | URL realurl = null;
22 | InputStream in = null;
23 | HttpURLConnection conn = null;
24 | realurl = new URL(url);
25 | conn = (HttpURLConnection) realurl.openConnection();
26 | conn.setDoOutput(true);
27 | conn.setRequestMethod("POST");
28 | String cookieStr = "";
29 | if (cookies != null) {
30 | for (Map.Entry entry : cookies.entrySet()) {
31 | cookieStr += (entry.getKey() + "=" + entry.getValue() + ";");
32 | }
33 | }
34 | conn.setRequestProperty("Cookie", cookieStr);
35 | PrintWriter pw = new PrintWriter(conn.getOutputStream());
36 | pw.print(params);
37 | pw.flush();
38 | pw.close();
39 | in = conn.getInputStream();
40 | return convertStreamToString(in);
41 | }
42 |
43 | public static String convertStreamToString(InputStream is) {
44 | if (is == null)
45 | return "";
46 | BufferedReader reader = new BufferedReader(new InputStreamReader(is));
47 | StringBuilder sb = new StringBuilder();
48 |
49 | String line = null;
50 | try {
51 | while ((line = reader.readLine()) != null) {
52 | sb.append(line);
53 | }
54 | } catch (IOException e) {
55 | e.printStackTrace();
56 | } finally {
57 | try {
58 | is.close();
59 | } catch (IOException e) {
60 | e.printStackTrace();
61 | }
62 | }
63 | return sb.toString();
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/java/com/casandroidclient/component/DecodeThread.java:
--------------------------------------------------------------------------------
1 | package com.casandroidclient.component;
2 |
3 | import android.os.Handler;
4 | import android.os.Looper;
5 |
6 | import com.casandroidclient.CaptureActivity;
7 | import com.google.zxing.BarcodeFormat;
8 | import com.google.zxing.DecodeHintType;
9 |
10 | import java.util.ArrayList;
11 | import java.util.Collection;
12 | import java.util.EnumMap;
13 | import java.util.EnumSet;
14 | import java.util.Map;
15 | import java.util.concurrent.CountDownLatch;
16 |
17 |
18 | public class DecodeThread extends Thread {
19 |
20 | public static final String BARCODE_BITMAP = "barcode_bitmap";
21 |
22 | public static final int BARCODE_MODE = 0X100;
23 | public static final int QRCODE_MODE = 0X200;
24 | public static final int ALL_MODE = 0X300;
25 |
26 | private final CaptureActivity activity;
27 | private final Map hints;
28 | private Handler handler;
29 | private final CountDownLatch handlerInitLatch;
30 |
31 | public DecodeThread(CaptureActivity activity, int decodeMode) {
32 |
33 | this.activity = activity;
34 | handlerInitLatch = new CountDownLatch(1);
35 |
36 | hints = new EnumMap(DecodeHintType.class);
37 |
38 | Collection decodeFormats = new ArrayList();
39 | decodeFormats.addAll(EnumSet.of(BarcodeFormat.AZTEC));
40 | decodeFormats.addAll(EnumSet.of(BarcodeFormat.PDF_417));
41 |
42 | switch (decodeMode) {
43 | case BARCODE_MODE:
44 | decodeFormats.addAll(DecodeFormatManager.getBarCodeFormats());
45 | break;
46 |
47 | case QRCODE_MODE:
48 | decodeFormats.addAll(DecodeFormatManager.getQrCodeFormats());
49 | break;
50 |
51 | case ALL_MODE:
52 | decodeFormats.addAll(DecodeFormatManager.getBarCodeFormats());
53 | decodeFormats.addAll(DecodeFormatManager.getQrCodeFormats());
54 | break;
55 |
56 | default:
57 | break;
58 | }
59 |
60 | hints.put(DecodeHintType.POSSIBLE_FORMATS, decodeFormats);
61 | }
62 |
63 | public Handler getHandler() {
64 | try {
65 | handlerInitLatch.await();
66 | } catch (InterruptedException ie) {
67 | // continue?
68 | }
69 | return handler;
70 | }
71 |
72 | @Override
73 | public void run() {
74 | Looper.prepare();
75 | handler = new DecodeHandler(activity, hints);
76 | handlerInitLatch.countDown();
77 | Looper.loop();
78 | }
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/cas/src/main/webapp/WEB-INF/web.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 | cas
7 |
8 | contextConfigLocation
9 |
10 | classpath:spring-mybatis.xml
11 | classpath:spring-component.xml
12 |
13 |
14 |
15 | org.springframework.web.context.ContextLoaderListener
16 |
17 |
18 |
19 | encodingFilter
20 | org.springframework.web.filter.CharacterEncodingFilter
21 |
22 | encoding
23 | UTF-8
24 |
25 |
26 | forceEncoding
27 | true
28 |
29 |
30 |
31 | encodingFilter
32 | /*
33 |
34 |
35 |
36 | authenticationFilter
37 | cas.filter.AuthenticationFilter
38 |
39 |
40 | authenticationFilter
41 | /authentication/validatetoken
42 |
43 |
44 |
45 | sessionFilter
46 | cas.filter.CacheSessionFilter
47 |
48 |
49 | sessionFilter
50 | /*
51 |
52 |
53 |
54 | dispatcherServlet
55 | org.springframework.web.servlet.DispatcherServlet
56 |
57 | contextConfigLocation
58 | classpath:springmvc.xml
59 |
60 | 1
61 |
62 |
63 | dispatcherServlet
64 | /
65 |
66 |
--------------------------------------------------------------------------------
/CasAndroidClient/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/cas/src/main/resources/spring-mybatis.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
24 |
25 |
26 |
27 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/cas/src/main/resources/springmvc.xml:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | application/json;charset=UTF-8
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/CasAndroidClient/app/src/main/java/com/casandroidclient/utils/InactivityTimer.java:
--------------------------------------------------------------------------------
1 | package com.casandroidclient.utils;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.app.Activity;
5 | import android.content.BroadcastReceiver;
6 | import android.content.Context;
7 | import android.content.Intent;
8 | import android.content.IntentFilter;
9 | import android.os.AsyncTask;
10 | import android.os.BatteryManager;
11 | import android.os.Build;
12 | import android.util.Log;
13 |
14 | /**
15 | * Finishes an activity after a period of inactivity if the device is on battery
16 | * power.
17 | */
18 | public class InactivityTimer {
19 |
20 | private static final String TAG = InactivityTimer.class.getSimpleName();
21 |
22 | private static final long INACTIVITY_DELAY_MS = 5 * 60 * 1000L;
23 |
24 | private Activity activity;
25 | private BroadcastReceiver powerStatusReceiver;
26 | private boolean registered;
27 | private AsyncTask