├── .gitignore
├── LICENSE
├── README.md
├── http
└── civism-sso.http
├── pom.xml
├── sql
└── sso.sql
└── src
├── main
├── java
│ └── com
│ │ └── civism
│ │ └── sso
│ │ ├── SsoApplication.java
│ │ ├── aop
│ │ └── GlobalExceptionAop.java
│ │ ├── config
│ │ ├── RedisAutoConfiguration.java
│ │ ├── ShiroConfig.java
│ │ ├── ShiroFilterRegisterConfig.java
│ │ └── SwaggerConfig.java
│ │ ├── constant
│ │ └── CivismConstant.java
│ │ ├── controller
│ │ └── IndexController.java
│ │ ├── dao
│ │ ├── SsoFunctionDao.java
│ │ ├── SsoProductDao.java
│ │ └── SsoUserDao.java
│ │ ├── entity
│ │ ├── AuthEntity.java
│ │ ├── BaseDO.java
│ │ ├── LoginEntity.java
│ │ ├── Response.java
│ │ ├── SsoFunctionDO.java
│ │ ├── SsoProductDO.java
│ │ ├── SsoUserDO.java
│ │ └── UserInfo.java
│ │ ├── enums
│ │ └── CustomExceptionEnum.java
│ │ ├── exception
│ │ └── CustomException.java
│ │ ├── filter
│ │ ├── BaseCheckFilter.java
│ │ ├── CheckLoginFilter.java
│ │ └── RefreshFilter.java
│ │ ├── redis
│ │ └── RedisClient.java
│ │ ├── service
│ │ ├── SsoFunctionService.java
│ │ ├── SsoProductService.java
│ │ ├── SsoUserService.java
│ │ └── impl
│ │ │ ├── SsoFunctionServiceImpl.java
│ │ │ ├── SsoProductServiceImpl.java
│ │ │ └── SsoUserServiceImpl.java
│ │ └── shiro
│ │ ├── CivismShiroUpmsRealm.java
│ │ ├── CustomRolePermissionResolver.java
│ │ ├── JavaUuidSessionIdGenerator.java
│ │ ├── RolePermission.java
│ │ ├── ShiroRedisCacheSessionDAO.java
│ │ ├── ShiroSessionManager.java
│ │ ├── UrlPathMatcher.java
│ │ ├── UrlPermission.java
│ │ └── UrlPermissionResolver.java
└── resources
│ ├── application.yml
│ └── mapper
│ └── sso_product.xml
└── test
└── java
└── com
└── civism
└── sso
└── SsoApplicationTests.java
/.gitignore:
--------------------------------------------------------------------------------
1 | *.classpath
2 | *.project
3 | install.bat
4 | /target
5 | *.settings
6 | target
7 | .idea
8 | *.iml
9 | .svn
10 | node_modules
11 | *.ipr
12 | *.iws
13 | .DS_Store
14 | /logs
15 | logs
16 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 说明
2 | 若需要springmvc版本,请切换到提交记录log:241cc8451ecef46e3b4467bd864c2768052f5123
3 | # 介绍
4 | civism-sso基于springmvc+redis+shiro 实现的分布式单点登录系统,继承了登录验证以及数据接口鉴权,
5 | 能很好的帮助其他项目做前后端分析,并且不需要其他子系统关心权限,并且该项目支持跨域请求
6 | # 功能介绍
7 | * sso登录:统一登录后,跳转任何子系统不需要再次登录
8 | * 鉴权:在子项目中,filter拦截所有数据请求转发到sso的/authorize路径,根据sso返回值来判断是否有权限访问
9 | * 跨域:sso支持不同域名的访问,采用了jsonp请求方式,返回可执行代码来达到跨域
10 | * 前后端分离:sso只有json接口返回,没有页面,跳转逻辑完全由前端控制,能更好的促进前后端分离开发
11 | # 操作步骤
12 | 1. 修改redis配置文件
13 | 2. 用jetty或tomcat启动civism-sso项目
14 | 3. 访问localhost:9999/login/index?userName=admin&password=123456&way=1&callback=hello获取token
15 | 4. 获取子系统菜单:localhost:9999/login/getMenus?hostName=www.baidu.com&callback=getMenus
16 | 5. 鉴权:localhost:9999/authorize?url=/civism/index.html会返回是否有权限
17 | # 说明
18 | * 除了以/login开头的不需要带token,其他的接口都需要把登录返回的token放到请求头中
19 | * 由于sso支持多个子系统,所有获取菜单的时候需要带域名,在数据库层次需要制定那些域名返回那些菜单,可以与权限集成,不同权限返回不同的菜单
20 | * 鉴权接口:该接口只验证了该用户在该角色的数据功能接口,所以设计数据库建议把菜单跟功能分离
21 | # 使用手册
22 | [使用说明](https://github.com/civism/civism-sso/wiki)
23 | # 具体接入介绍
24 | https://www.jianshu.com/p/1603c60f1de6
25 |
--------------------------------------------------------------------------------
/http/civism-sso.http:
--------------------------------------------------------------------------------
1 | ### 鉴权
2 | GET http://localhost:8081/sso/auth
3 | Accept: application/json
4 | Token: 871138b5458c45f3a6a9b09235bdbde9
5 |
6 |
7 | ### 登录信息
8 | POST http://localhost:8081/sso/login
9 | Content-Type: application/json
10 |
11 | {
12 | "userName": "admin",
13 | "password": "123456"
14 | }
15 |
16 | ###
17 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | org.springframework.boot
8 | spring-boot-starter-parent
9 | 2.2.1.RELEASE
10 |
11 |
12 | com.civism
13 | sso
14 | 2.0.0-SNAPSHOT
15 | sso
16 | sso-web
17 |
18 |
19 | 1.8
20 | 1.4.2
21 | 3.2.0
22 | 1.1.21
23 | 2.1.1
24 | 1.2.10
25 | 2.9.2
26 | 1.2.62
27 |
28 |
29 |
30 |
31 |
32 |
33 | org.apache.shiro
34 | shiro-core
35 | ${shiro-version}
36 |
37 |
38 | org.apache.shiro
39 | shiro-web
40 | ${shiro-version}
41 |
42 |
43 | org.apache.shiro
44 | shiro-spring
45 | ${shiro-version}
46 |
47 |
48 |
49 |
50 | com.baomidou
51 | mybatis-plus-boot-starter
52 | ${mybatis-plus-version}
53 |
54 |
55 |
56 | com.baomidou
57 | mybatis-plus-generator
58 | 3.2.0
59 |
60 |
61 |
62 |
63 | com.alibaba
64 | druid-spring-boot-starter
65 | ${druid-spring-boot-version}
66 |
67 |
68 |
69 | org.mybatis.spring.boot
70 | mybatis-spring-boot-starter
71 | ${mybatis-spring-boot-version}
72 |
73 |
74 |
75 | com.github.pagehelper
76 | pagehelper-spring-boot-starter
77 | ${pagehelper-version}
78 |
79 |
80 |
81 | io.springfox
82 | springfox-swagger2
83 | ${springfox-swagger-version}
84 |
85 |
86 |
87 | io.springfox
88 | springfox-swagger-ui
89 | ${springfox-swagger-version}
90 |
91 |
92 |
93 | com.alibaba
94 | fastjson
95 | ${fastjosn-version}
96 |
97 |
98 |
99 | org.springframework.boot
100 | spring-boot-starter-aop
101 |
102 |
103 |
104 | org.apache.commons
105 | commons-lang3
106 |
107 |
108 |
109 | javax.servlet
110 | javax.servlet-api
111 |
112 |
113 |
114 | mysql
115 | mysql-connector-java
116 |
117 |
118 |
119 |
120 | org.springframework.boot
121 | spring-boot-starter
122 |
123 |
124 |
125 | org.springframework.boot
126 | spring-boot-starter-data-redis
127 |
128 |
129 |
130 | org.projectlombok
131 | lombok
132 | true
133 |
134 |
135 | org.springframework.boot
136 | spring-boot-starter-test
137 | test
138 |
139 |
140 | org.junit.vintage
141 | junit-vintage-engine
142 |
143 |
144 |
145 |
146 | org.springframework.boot
147 | spring-boot-starter-web
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 | org.springframework.boot
156 | spring-boot-maven-plugin
157 |
158 |
159 |
160 |
161 |
162 |
--------------------------------------------------------------------------------
/sql/sso.sql:
--------------------------------------------------------------------------------
1 | #系统表
2 | CREATE TABLE `civism-sso`.`sso_product`
3 | (
4 | `id` INT NOT NULL AUTO_INCREMENT,
5 | `name` VARCHAR(45) NOT NULL,
6 | `grd_delete` TINYINT(1) NOT NULL COMMENT '逻辑删除 0 正常1删除',
7 | `gmt_create` DATETIME NOT NULL,
8 | `gmt_modified` DATETIME NOT NULL,
9 | PRIMARY KEY (`id`)
10 | );
11 |
12 | #用户表
13 | CREATE TABLE `civism-sso`.`sso_user`
14 | (
15 | `id` INT NOT NULL AUTO_INCREMENT,
16 | `name` VARCHAR(45) NOT NULL,
17 | `password` VARCHAR(45) NOT NULL,
18 | `grd_delete` TINYINT(1) NOT NULL,
19 | `gmt_create` DATETIME NOT NULL,
20 | `gmt_modified` DATETIME NOT NULL,
21 | PRIMARY KEY (`id`)
22 | );
23 | #菜单表
24 | CREATE TABLE `civism-sso`.`sso_menu`
25 | (
26 | `id` INT NOT NULL AUTO_INCREMENT,
27 | `name` VARCHAR(45) NOT NULL COMMENT '菜单名称',
28 | `grd_delete` TINYINT(1) NOT NULL,
29 | `gmt_create` DATETIME NOT NULL,
30 | `gmt_modified` DATETIME NOT NULL,
31 | PRIMARY KEY (`id`)
32 | );
33 | #功能表
34 | CREATE TABLE `civism-sso`.`sso_function`
35 | (
36 | `id` INT NOT NULL AUTO_INCREMENT,
37 | `name` VARCHAR(45) NOT NULL,
38 | `url` VARCHAR(45) NOT NULL,
39 | `method` VARCHAR(45) NOT NULL,
40 | `menu_id` INT(11) NULL,
41 | `grd_delete` TINYINT(1) NOT NULL,
42 | `gmt_create` DATETIME NOT NULL,
43 | `gmt_modified` DATETIME NOT NULL,
44 | PRIMARY KEY (`id`)
45 | );
46 |
47 | INSERT INTO `civism-sso`.`sso_user`(`name`, `password`, `grd_delete`, `gmt_create`, `gmt_modified`) VALUES ('admin', '123456', 0, now(),now());
48 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/SsoApplication.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso;
2 |
3 | import org.mybatis.spring.annotation.MapperScan;
4 | import org.springframework.boot.SpringApplication;
5 | import org.springframework.boot.autoconfigure.SpringBootApplication;
6 |
7 | /**
8 | * @author : Civism
9 | * @projectName : civism-sso
10 | * @E-mail : 695234456@qq.com
11 | */
12 | @SpringBootApplication
13 | @MapperScan("com.civism.sso.dao")
14 | public class SsoApplication {
15 |
16 | public static void main(String[] args) {
17 | SpringApplication.run(SsoApplication.class, args);
18 | }
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/aop/GlobalExceptionAop.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.aop;
2 |
3 | import com.civism.sso.entity.Response;
4 | import com.civism.sso.enums.CustomExceptionEnum;
5 | import com.civism.sso.exception.CustomException;
6 | import lombok.extern.slf4j.Slf4j;
7 | import org.aspectj.lang.ProceedingJoinPoint;
8 | import org.aspectj.lang.Signature;
9 | import org.aspectj.lang.annotation.Around;
10 | import org.aspectj.lang.annotation.Aspect;
11 | import org.springframework.stereotype.Component;
12 |
13 | /**
14 | * @author : Civism
15 | * @projectName : civism-sso
16 | * @E-mail : 695234456@qq.com
17 | */
18 | @Component
19 | @Aspect
20 | @Slf4j
21 | public class GlobalExceptionAop {
22 |
23 | private final String POINT_CUT = "execution(public * com.civism.sso.controller.*.*(..))";
24 |
25 | @Around(value = POINT_CUT)
26 | public Object around(ProceedingJoinPoint proceedingJoinPoint) {
27 | Signature signature = proceedingJoinPoint.getSignature();
28 | long t = System.currentTimeMillis();
29 | try {
30 | Object result = proceedingJoinPoint.proceed();
31 | printErrorLog(proceedingJoinPoint, signature, t);
32 | return result;
33 | } catch (CustomException ex) {
34 | printErrorLog(proceedingJoinPoint, signature, t);
35 | return new Response<>(ex);
36 | } catch (Exception e) {
37 | printErrorLog(proceedingJoinPoint, signature, t);
38 | return new Response<>(CustomExceptionEnum.SYSTEM_ERROR);
39 | } catch (Throwable throwable) {
40 | printErrorLog(proceedingJoinPoint, signature, t);
41 | return new Response<>(CustomExceptionEnum.SYSTEM_ERROR);
42 | }
43 | }
44 |
45 | private void printErrorLog(ProceedingJoinPoint proceedingJoinPoint, Signature signature, long t) {
46 | log.info("类名:{}-方法名:{}-传入参数:{}###总共耗时:{}毫秒", signature.getDeclaringTypeName(),
47 | signature.getName(), proceedingJoinPoint.getArgs(),
48 | System.currentTimeMillis() - t);
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/config/RedisAutoConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.config;
2 |
3 | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 | import org.springframework.data.redis.connection.RedisConnectionFactory;
7 | import org.springframework.data.redis.core.RedisTemplate;
8 |
9 | /**
10 | * @author : Civism
11 | * @projectName : civism-sso
12 | * @E-mail : 695234456@qq.com
13 | */
14 | @Configuration
15 | public class RedisAutoConfiguration {
16 |
17 |
18 | @Bean
19 | @ConditionalOnMissingBean(name = "redisTemplate")
20 | public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
21 | RedisTemplate template = new RedisTemplate<>();
22 | template.setConnectionFactory(redisConnectionFactory);
23 | return template;
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/config/ShiroConfig.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.config;
2 |
3 | import com.civism.sso.filter.CheckLoginFilter;
4 | import com.civism.sso.filter.RefreshFilter;
5 | import com.civism.sso.shiro.*;
6 | import org.apache.shiro.mgt.SecurityManager;
7 | import org.apache.shiro.realm.Realm;
8 | import org.apache.shiro.session.mgt.SessionManager;
9 | import org.apache.shiro.session.mgt.eis.SessionDAO;
10 | import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
11 | import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
12 | import org.springframework.context.annotation.Bean;
13 | import org.springframework.context.annotation.Configuration;
14 |
15 | import javax.servlet.Filter;
16 | import java.util.HashMap;
17 | import java.util.LinkedHashMap;
18 | import java.util.Map;
19 |
20 | /**
21 | * @author : Civism
22 | * @projectName : civism-sso
23 | * @E-mail : 695234456@qq.com
24 | */
25 | @Configuration
26 | public class ShiroConfig {
27 |
28 | @Bean
29 | public SessionManager sessionManager() {
30 | ShiroSessionManager shiroSessionManager = new ShiroSessionManager();
31 | shiroSessionManager.setGlobalSessionTimeout(86400000);
32 | shiroSessionManager.setDeleteInvalidSessions(true);
33 | shiroSessionManager.setSessionValidationInterval(1800000);
34 |
35 | shiroSessionManager.setSessionDAO(getSession());
36 | shiroSessionManager.getSessionIdCookie().setName("SHIRO-SESSIONID");
37 | //是否开启定时调度器进行检测过期session 默认为true
38 | shiroSessionManager.setSessionValidationSchedulerEnabled(true);
39 | //取消url 后面的 JSESSIONID
40 | shiroSessionManager.setSessionIdUrlRewritingEnabled(false);
41 | return shiroSessionManager;
42 | }
43 |
44 | @Bean
45 | public SessionDAO getSession() {
46 | ShiroRedisCacheSessionDAO shiroRedisCacheSessionDAO = new ShiroRedisCacheSessionDAO();
47 | shiroRedisCacheSessionDAO.setSessionIdGenerator(new JavaUuidSessionIdGenerator());
48 | return shiroRedisCacheSessionDAO;
49 | }
50 |
51 | @Bean
52 | public CheckLoginFilter getCheckLoginFilter() {
53 | return new CheckLoginFilter();
54 | }
55 |
56 | @Bean
57 | public RefreshFilter getRefreshFilter() {
58 | return new RefreshFilter();
59 | }
60 |
61 | @Bean
62 | public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
63 | ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
64 | shiroFilterFactoryBean.setSecurityManager(securityManager);
65 |
66 | Map filters = new HashMap<>();
67 |
68 | filters.put("checkLogin", getCheckLoginFilter());
69 | filters.put("refresh", getCheckLoginFilter());
70 |
71 | shiroFilterFactoryBean.setFilters(filters);
72 |
73 | //拦截器.
74 | Map filterChainDefinitionMap = new LinkedHashMap<>();
75 |
76 | filterChainDefinitionMap.put("/sso/login", "anon");
77 | filterChainDefinitionMap.put("/**", "checkLogin,refresh");
78 | shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
79 | return shiroFilterFactoryBean;
80 | }
81 |
82 | @Bean
83 | public SecurityManager getSecurityManager() {
84 | DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
85 | defaultWebSecurityManager.setSessionManager(sessionManager());
86 | defaultWebSecurityManager.setRealm(getRealm());
87 | return defaultWebSecurityManager;
88 | }
89 |
90 | @Bean
91 | public Realm getRealm() {
92 | CivismShiroUpmsRealm civismShiroUpmsRealm = new CivismShiroUpmsRealm();
93 | UrlPermissionResolver urlPermissionResolver = new UrlPermissionResolver();
94 | // CustomRolePermissionResolver customRolePermissionResolver = new CustomRolePermissionResolver();
95 | // civismShiroUpmsRealm.setRolePermissionResolver(customRolePermissionResolver);
96 | civismShiroUpmsRealm.setPermissionResolver(urlPermissionResolver);
97 | return civismShiroUpmsRealm;
98 | }
99 |
100 | }
101 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/config/ShiroFilterRegisterConfig.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.config;
2 |
3 |
4 | import com.civism.sso.filter.CheckLoginFilter;
5 | import org.springframework.boot.web.servlet.FilterRegistrationBean;
6 | import org.springframework.context.annotation.Bean;
7 | import org.springframework.context.annotation.Configuration;
8 |
9 | /**
10 | * @author : Civism
11 | * @projectName : civism-sso
12 | * @E-mail : 695234456@qq.com
13 | */
14 | @Configuration
15 | public class ShiroFilterRegisterConfig {
16 |
17 | @Bean
18 | public FilterRegistrationBean permissionFilterRegistration(CheckLoginFilter filter) {
19 | FilterRegistrationBean registration = new FilterRegistrationBean(filter);
20 | registration.setEnabled(false);
21 | return registration;
22 | }
23 | //
24 | // @Bean
25 | // public FilterRegistrationBean refreshFilterRegistration(RefreshFilter filter) {
26 | // FilterRegistrationBean registration = new FilterRegistrationBean(filter);
27 | // registration.setEnabled(false);
28 | // return registration;
29 | // }
30 | //
31 | // @Bean
32 | // public FilterRegistrationBean infoPowerRegistration(InfoPowerFilter filter){
33 | // FilterRegistrationBean registration = new FilterRegistrationBean(filter);
34 | // registration.setEnabled(false);
35 | // return registration;
36 | // }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/config/SwaggerConfig.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.config;
2 |
3 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 | import springfox.documentation.builders.ApiInfoBuilder;
7 | import springfox.documentation.builders.ParameterBuilder;
8 | import springfox.documentation.builders.PathSelectors;
9 | import springfox.documentation.builders.RequestHandlerSelectors;
10 | import springfox.documentation.schema.ModelRef;
11 | import springfox.documentation.service.ApiInfo;
12 | import springfox.documentation.service.Parameter;
13 | import springfox.documentation.spi.DocumentationType;
14 | import springfox.documentation.spring.web.plugins.Docket;
15 | import springfox.documentation.swagger2.annotations.EnableSwagger2;
16 |
17 | import java.util.ArrayList;
18 | import java.util.List;
19 |
20 | /**
21 | * @author : Civism
22 | * @projectName : civism-sso
23 | * @E-mail : 695234456@qq.com
24 | */
25 | @Configuration
26 | @EnableSwagger2
27 | @ConditionalOnProperty(prefix = "swagger", value = {"enable"}, havingValue = "true")
28 | public class SwaggerConfig {
29 |
30 | @Bean
31 | public Docket createRestApi() {
32 | ParameterBuilder tokenPar = new ParameterBuilder();
33 | List pars = new ArrayList<>();
34 | tokenPar.name("token").description("令牌")
35 | .modelRef(new ModelRef("string")).parameterType("header").required(true).build();
36 | pars.add(tokenPar.build());
37 | return new Docket(DocumentationType.SWAGGER_2)
38 | .apiInfo(apiInfo())
39 | .select()
40 | .apis(RequestHandlerSelectors.basePackage("com.xc.info.controller"))
41 | .paths(PathSelectors.any())
42 | .build().globalOperationParameters(pars);
43 | }
44 |
45 |
46 | private ApiInfo apiInfo() {
47 | return new ApiInfoBuilder()
48 | .title("基础信息管理")
49 | .description("基础信息接口文档")
50 | .version("2.0.0")
51 | .build();
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/constant/CivismConstant.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.constant;
2 |
3 | import java.io.Serializable;
4 |
5 | /**
6 | * @author : Civism
7 | * @projectName : civism-sso
8 | * @E-mail : 695234456@qq.com
9 | */
10 | public class CivismConstant implements Serializable {
11 |
12 | private static final long serialVersionUID = 1751077975755493749L;
13 |
14 | /**
15 | * redis中的token
16 | */
17 | public static final String TOKEN = "token";
18 |
19 | /**
20 | * 登陆有效期
21 | */
22 | public static final Long EXPIRE = 30 * 60 * 1L;
23 | }
24 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/controller/IndexController.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.controller;
2 |
3 | import com.civism.sso.entity.LoginEntity;
4 | import io.swagger.annotations.Api;
5 | import io.swagger.annotations.ApiOperation;
6 | import lombok.extern.slf4j.Slf4j;
7 | import org.apache.shiro.SecurityUtils;
8 | import org.apache.shiro.authc.UsernamePasswordToken;
9 | import org.apache.shiro.subject.Subject;
10 | import org.springframework.web.bind.annotation.*;
11 |
12 | import javax.servlet.http.HttpServletRequest;
13 |
14 | /**
15 | * @author : Civism
16 | * @projectName : civism-sso
17 | * @E-mail : 695234456@qq.com
18 | */
19 | @RestController
20 | @RequestMapping("/sso")
21 | @Api(tags = "登陆接口")
22 | @Slf4j
23 | public class IndexController {
24 |
25 |
26 | @ApiOperation("登陆")
27 | @PostMapping("/login")
28 | public Object login(@RequestBody LoginEntity loginEntity) {
29 | UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken();
30 | usernamePasswordToken.setUsername(loginEntity.getUserName());
31 | usernamePasswordToken.setPassword(loginEntity.getPassword().toCharArray());
32 | Subject subject = SecurityUtils.getSubject();
33 | subject.login(usernamePasswordToken);
34 | if (subject.isAuthenticated()) {
35 | return SecurityUtils.getSubject().getPrincipal();
36 | }
37 | return null;
38 | }
39 |
40 | @ApiOperation("鉴权")
41 | @GetMapping("/auth")
42 | public Boolean authenticate(HttpServletRequest request) {
43 | String servletPath = request.getServletPath();
44 | return SecurityUtils.getSubject().isPermitted(servletPath);
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/dao/SsoFunctionDao.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.dao;
2 |
3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 | import com.civism.sso.entity.SsoFunctionDO;
5 |
6 | /**
7 | * @author : Civism
8 | * @projectName : civism-sso
9 | * @E-mail : 695234456@qq.com
10 | */
11 | public interface SsoFunctionDao extends BaseMapper {
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/dao/SsoProductDao.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.dao;
2 |
3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 | import com.civism.sso.entity.SsoProductDO;
5 |
6 | /**
7 | * @author : Civism
8 | * @projectName : civism-sso
9 | * @E-mail : 695234456@qq.com
10 | */
11 | public interface SsoProductDao extends BaseMapper {
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/dao/SsoUserDao.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.dao;
2 |
3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 | import com.civism.sso.entity.SsoUserDO;
5 |
6 | /**
7 | * @author : Civism
8 | * @projectName : civism-sso
9 | * @E-mail : 695234456@qq.com
10 | */
11 | public interface SsoUserDao extends BaseMapper {
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/entity/AuthEntity.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.entity;
2 |
3 | import java.io.Serializable;
4 |
5 | /**
6 | * @author : Civism
7 | * @projectName : civism-sso
8 | * @E-mail : 695234456@qq.com
9 | */
10 | public class AuthEntity implements Serializable {
11 |
12 | private static final long serialVersionUID = 139913275235343163L;
13 |
14 |
15 | private String requestUrl;
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/entity/BaseDO.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import com.baomidou.mybatisplus.annotation.TableLogic;
6 | import lombok.Data;
7 |
8 | import java.io.Serializable;
9 | import java.util.Date;
10 | /**
11 | * @author : Civism
12 | * @projectName : civism-sso
13 | * @E-mail : 695234456@qq.com
14 | */
15 | @Data
16 | public class BaseDO implements Serializable {
17 |
18 | private static final long serialVersionUID = -5048221139649128719L;
19 |
20 | @TableId(type = IdType.AUTO)
21 | private Integer id;
22 |
23 | private Date gmtCreate;
24 |
25 | private Date gmtModified;
26 |
27 | @TableLogic
28 | private Integer grdDelete;
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/entity/LoginEntity.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.entity;
2 |
3 | import io.swagger.annotations.ApiModelProperty;
4 | import lombok.Data;
5 |
6 | import java.io.Serializable;
7 | /**
8 | * @author : Civism
9 | * @projectName : civism-sso
10 | * @E-mail : 695234456@qq.com
11 | */
12 | @Data
13 | public class LoginEntity implements Serializable {
14 |
15 | private static final long serialVersionUID = 2449244918272018993L;
16 |
17 | /**
18 | * 用户名称
19 | */
20 | @ApiModelProperty("用户名称")
21 | private String userName;
22 |
23 | /**
24 | * 用户密码
25 | */
26 | @ApiModelProperty("用户密码")
27 | private String password;
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/entity/Response.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.entity;
2 |
3 | import com.civism.sso.exception.CustomException;
4 | import java.io.Serializable;
5 |
6 | /**
7 | * @author : Civism
8 | * @projectName : civism-sso
9 | * @E-mail : 695234456@qq.com
10 | */
11 | public class Response implements Serializable {
12 |
13 | private static final long serialVersionUID = 8817463078594954274L;
14 |
15 | private boolean success;
16 |
17 | private T data;
18 |
19 | private String errorCode;
20 |
21 | private String errorMsg;
22 |
23 |
24 | public Response(T data) {
25 | if (data instanceof CustomException) {
26 | CustomException customException = (CustomException) data;
27 | this.errorCode = customException.getErrorCode();
28 | this.errorMsg = customException.getErrorMsg();
29 | } else {
30 | this.data = data;
31 | this.success = true;
32 | }
33 | }
34 |
35 |
36 | public boolean isSuccess() {
37 | return success;
38 | }
39 |
40 | public void setSuccess(boolean success) {
41 | this.success = success;
42 | }
43 |
44 | public T getData() {
45 | return data;
46 | }
47 |
48 | public void setData(T data) {
49 | this.data = data;
50 | }
51 |
52 | public String getErrorCode() {
53 | return errorCode;
54 | }
55 |
56 | public void setErrorCode(String errorCode) {
57 | this.errorCode = errorCode;
58 | }
59 |
60 | public String getErrorMsg() {
61 | return errorMsg;
62 | }
63 |
64 | public void setErrorMsg(String errorMsg) {
65 | this.errorMsg = errorMsg;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/entity/SsoFunctionDO.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.TableName;
4 | import lombok.Data;
5 |
6 | /**
7 | * @author : Civism
8 | * @projectName : civism-sso
9 | * @E-mail : 695234456@qq.com
10 | */
11 | @Data
12 | @TableName("sso_function")
13 | public class SsoFunctionDO extends BaseDO {
14 |
15 | private static final long serialVersionUID = -420032538363892799L;
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/entity/SsoProductDO.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.TableName;
4 | import lombok.Data;
5 |
6 | /**
7 | * @author : Civism
8 | * @projectName : civism-sso
9 | * @E-mail : 695234456@qq.com
10 | */
11 | @Data
12 | @TableName("sso_product")
13 | public class SsoProductDO extends BaseDO {
14 |
15 | private static final long serialVersionUID = 5019247183721310811L;
16 |
17 | private String name;
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/entity/SsoUserDO.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.TableName;
4 | import lombok.Data;
5 |
6 | /**
7 | * @author : Civism
8 | * @projectName : civism-sso
9 | * @E-mail : 695234456@qq.com
10 | */
11 | @Data
12 | @TableName("sso_user")
13 | public class SsoUserDO extends BaseDO {
14 |
15 | private static final long serialVersionUID = -898944646564104445L;
16 |
17 | /**
18 | * 账号密码
19 | */
20 | private String name;
21 |
22 | /**
23 | * 密码
24 | */
25 | private String password;
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/entity/UserInfo.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.entity;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Builder;
5 | import lombok.Data;
6 | import lombok.NoArgsConstructor;
7 |
8 | import java.io.Serializable;
9 |
10 | /**
11 | * @author : Civism
12 | * @projectName : civism-sso
13 | * @E-mail : 695234456@qq.com
14 | */
15 | @Builder
16 | @Data
17 | @NoArgsConstructor
18 | @AllArgsConstructor
19 | public class UserInfo implements Serializable {
20 |
21 | private static final long serialVersionUID = -2253372833687147328L;
22 |
23 | /**
24 | * 用户id
25 | */
26 | private Integer id;
27 |
28 | /**
29 | * 用户名称
30 | */
31 | private String name;
32 |
33 | /**
34 | * 用户token
35 | */
36 | private String token;
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/enums/CustomExceptionEnum.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.enums;
2 |
3 | /**
4 | * @author : Civism
5 | * @version 1.0
6 | * @projectName:civism-sso
7 | * @E-mail:695234456@qq.com
8 | */
9 | public enum CustomExceptionEnum {
10 | ACCOUNT_PASSWORD_ERROR("U001", "用户名或密码错误"),
11 | NO_LOGIN("U002", "登陆过期"),
12 | NO_POWER("U003", "没有权限"),
13 | SYSTEM_ERROR("Z999", "系统异常");
14 |
15 | CustomExceptionEnum(String code, String errorMsg) {
16 | this.code = code;
17 | this.errorMsg = errorMsg;
18 | }
19 |
20 | private String code;
21 |
22 | private String errorMsg;
23 |
24 | public String getCode() {
25 | return code;
26 | }
27 |
28 | public void setCode(String code) {
29 | this.code = code;
30 | }
31 |
32 | public String getErrorMsg() {
33 | return errorMsg;
34 | }
35 |
36 | public void setErrorMsg(String errorMsg) {
37 | this.errorMsg = errorMsg;
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/exception/CustomException.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.exception;
2 |
3 | import com.civism.sso.enums.CustomExceptionEnum;
4 | import org.apache.shiro.authc.AuthenticationException;
5 |
6 | /**
7 | * @author : Civism
8 | * @projectName : civism-sso
9 | * @E-mail : 695234456@qq.com
10 | */
11 | public class CustomException extends AuthenticationException {
12 |
13 | private String errorCode;
14 | private String errorMsg;
15 |
16 | public CustomException(CustomExceptionEnum exceptionEnum) {
17 | this.errorCode = exceptionEnum.getCode();
18 | this.errorMsg = exceptionEnum.getErrorMsg();
19 | }
20 |
21 |
22 | public String getErrorCode() {
23 | return errorCode;
24 | }
25 |
26 | public String getErrorMsg() {
27 | return errorMsg;
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/filter/BaseCheckFilter.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.filter;
2 |
3 | import com.alibaba.fastjson.JSON;
4 | import com.civism.sso.entity.Response;
5 | import com.civism.sso.exception.CustomException;
6 | import org.apache.shiro.web.filter.authc.UserFilter;
7 |
8 | import javax.servlet.ServletRequest;
9 | import javax.servlet.ServletResponse;
10 | import javax.servlet.http.HttpServletResponse;
11 | import java.io.PrintWriter;
12 |
13 | /**
14 | * @author : Civism
15 | * @projectName : civism-sso
16 | * @E-mail : 695234456@qq.com
17 | */
18 | public abstract class BaseCheckFilter extends UserFilter {
19 |
20 | protected abstract void checkFail() throws CustomException;
21 |
22 | @Override
23 | protected boolean onAccessDenied(ServletRequest req, ServletResponse resp)
24 | throws Exception {
25 |
26 | PrintWriter out = null;
27 | try {
28 | checkFail();
29 | return super.onAccessDenied(req, resp);
30 | } catch (CustomException e) {
31 | HttpServletResponse response = (HttpServletResponse) resp;
32 | response.setCharacterEncoding("UTF-8");
33 | response.setHeader("Content-Type", "application/json;charset=utf-8");
34 | response.setContentType("application/json;charset=UTF-8");
35 | out = response.getWriter();
36 | out.write(JSON.toJSONString(new Response<>(e)));
37 | } finally {
38 | if (out != null) {
39 | out.close();
40 | }
41 | }
42 | return false;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/filter/CheckLoginFilter.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.filter;
2 |
3 | import com.civism.sso.constant.CivismConstant;
4 | import com.civism.sso.enums.CustomExceptionEnum;
5 | import com.civism.sso.exception.CustomException;
6 | import com.civism.sso.redis.RedisClient;
7 | import org.apache.commons.lang3.StringUtils;
8 |
9 | import javax.annotation.Resource;
10 | import javax.servlet.ServletRequest;
11 | import javax.servlet.ServletResponse;
12 | import javax.servlet.http.HttpServletRequest;
13 |
14 | /**
15 | * @author : Civism
16 | * @projectName : civism-sso
17 | * @E-mail : 695234456@qq.com
18 | */
19 | public class CheckLoginFilter extends BaseCheckFilter {
20 |
21 | @Resource
22 | private RedisClient redisClient;
23 |
24 | @Override
25 | protected boolean isAccessAllowed(ServletRequest req, ServletResponse resp, Object mappedValue) {
26 |
27 | HttpServletRequest request = (HttpServletRequest) req;
28 | String token = request.getHeader(CivismConstant.TOKEN);
29 | if (StringUtils.isEmpty(token)) {
30 | return false;
31 | }
32 | Object o = redisClient.get(token);
33 | return o != null;
34 |
35 |
36 | }
37 |
38 | @Override
39 | protected void checkFail() throws CustomException {
40 | throw new CustomException(CustomExceptionEnum.NO_LOGIN);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/filter/RefreshFilter.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.filter;
2 |
3 | import com.civism.sso.redis.RedisClient;
4 | import org.apache.shiro.web.filter.authc.UserFilter;
5 |
6 | import javax.annotation.Resource;
7 | import javax.servlet.ServletRequest;
8 | import javax.servlet.ServletResponse;
9 | import javax.servlet.http.HttpServletRequest;
10 |
11 | import static com.civism.sso.constant.CivismConstant.EXPIRE;
12 | import static com.civism.sso.constant.CivismConstant.TOKEN;
13 |
14 | /**
15 | * @author : Civism
16 | * @projectName : civism-sso
17 | * @E-mail : 695234456@qq.com
18 | */
19 | public class RefreshFilter extends UserFilter {
20 |
21 | @Resource
22 | private RedisClient redisClient;
23 |
24 | @Override
25 | protected boolean isAccessAllowed(ServletRequest req, ServletResponse response, Object mappedValue) {
26 | HttpServletRequest request = (HttpServletRequest) req;
27 | String token = request.getHeader(TOKEN);
28 | redisClient.expire(token, EXPIRE);
29 | return super.isAccessAllowed(request, response, mappedValue);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/redis/RedisClient.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.redis;
2 |
3 | import org.springframework.data.redis.core.RedisTemplate;
4 | import org.springframework.stereotype.Component;
5 |
6 | import javax.annotation.Resource;
7 | import java.util.concurrent.TimeUnit;
8 |
9 | /**
10 | * @author : Civism
11 | * @projectName : civism-sso
12 | * @E-mail : 695234456@qq.com
13 | */
14 | @Component
15 | public class RedisClient {
16 |
17 | @Resource
18 | private RedisTemplate redisTemplate;
19 |
20 | /**
21 | * 设置过期时间
22 | *
23 | * @param timeOut 超时时间 单位秒
24 | */
25 | public void set(String key, Object value, long timeOut) {
26 | redisTemplate.opsForValue().set(key, value, timeOut, TimeUnit.SECONDS);
27 | }
28 |
29 | /**
30 | * 永不过期(相对意义)
31 | */
32 | public void set(String key, Object value) {
33 | redisTemplate.opsForValue().set(key, value);
34 | }
35 |
36 | /**
37 | * 删除
38 | */
39 | public boolean delete(String key) {
40 | return redisTemplate.delete(key);
41 | }
42 |
43 | /**
44 | *
45 | */
46 | public Object get(String key) {
47 | return redisTemplate.opsForValue().get(key);
48 | }
49 |
50 | /**
51 | * 刷新key实效
52 | * @param key
53 | * @param time
54 | */
55 | public void expire(String key, long time) {
56 | redisTemplate.expire(key, time, TimeUnit.SECONDS);
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/service/SsoFunctionService.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.service;
2 |
3 | import com.baomidou.mybatisplus.extension.service.IService;
4 | import com.civism.sso.entity.SsoFunctionDO;
5 |
6 | /**
7 | * @author : Civism
8 | * @projectName : civism-sso
9 | * @E-mail : 695234456@qq.com
10 | */
11 | public interface SsoFunctionService extends IService {
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/service/SsoProductService.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.service;
2 |
3 | import com.baomidou.mybatisplus.extension.service.IService;
4 | import com.civism.sso.entity.SsoProductDO;
5 |
6 | /**
7 | * @author : Civism
8 | * @projectName : civism-sso
9 | * @E-mail : 695234456@qq.com
10 | */
11 | public interface SsoProductService extends IService {
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/service/SsoUserService.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.service;
2 |
3 | import com.baomidou.mybatisplus.extension.service.IService;
4 | import com.civism.sso.entity.SsoUserDO;
5 |
6 | /**
7 | * @author : Civism
8 | * @projectName : civism-sso
9 | * @E-mail : 695234456@qq.com
10 | */
11 | public interface SsoUserService extends IService {
12 |
13 | /**
14 | * 通过用户名和密码查找用户
15 | * @param userName
16 | * @return
17 | */
18 | SsoUserDO queryUserByUserName(String userName);
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/service/impl/SsoFunctionServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.service.impl;
2 |
3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
4 | import com.civism.sso.dao.SsoFunctionDao;
5 | import com.civism.sso.entity.SsoFunctionDO;
6 | import com.civism.sso.service.SsoFunctionService;
7 | import org.springframework.stereotype.Service;
8 |
9 | /**
10 | * @author : Civism
11 | * @projectName : civism-sso
12 | * @E-mail : 695234456@qq.com
13 | */
14 | @Service
15 | public class SsoFunctionServiceImpl extends ServiceImpl implements SsoFunctionService {
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/service/impl/SsoProductServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.service.impl;
2 |
3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
4 | import com.civism.sso.dao.SsoProductDao;
5 | import com.civism.sso.entity.SsoProductDO;
6 | import com.civism.sso.service.SsoProductService;
7 | import org.springframework.stereotype.Service;
8 | /**
9 | * @author : Civism
10 | * @projectName : civism-sso
11 | * @E-mail : 695234456@qq.com
12 | */
13 | @Service
14 | public class SsoProductServiceImpl extends ServiceImpl implements SsoProductService {
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/service/impl/SsoUserServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.service.impl;
2 |
3 | import com.baomidou.mybatisplus.core.toolkit.Wrappers;
4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
5 | import com.civism.sso.dao.SsoUserDao;
6 | import com.civism.sso.entity.SsoUserDO;
7 | import com.civism.sso.service.SsoUserService;
8 | import org.springframework.stereotype.Service;
9 |
10 | /**
11 | * @author : Civism
12 | * @projectName : civism-sso
13 | * @E-mail : 695234456@qq.com
14 | */
15 | @Service
16 | public class SsoUserServiceImpl extends ServiceImpl implements SsoUserService {
17 |
18 | @Override
19 | public SsoUserDO queryUserByUserName(String userName) {
20 | return this.getOne(Wrappers.lambdaQuery().eq(SsoUserDO::getName, userName));
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/shiro/CivismShiroUpmsRealm.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.shiro;
2 |
3 | import com.civism.sso.constant.CivismConstant;
4 | import com.civism.sso.entity.SsoUserDO;
5 | import com.civism.sso.entity.UserInfo;
6 | import com.civism.sso.enums.CustomExceptionEnum;
7 | import com.civism.sso.exception.CustomException;
8 | import com.civism.sso.redis.RedisClient;
9 | import com.civism.sso.service.SsoUserService;
10 | import org.apache.shiro.SecurityUtils;
11 | import org.apache.shiro.authc.AuthenticationException;
12 | import org.apache.shiro.authc.AuthenticationInfo;
13 | import org.apache.shiro.authc.AuthenticationToken;
14 | import org.apache.shiro.authc.SimpleAuthenticationInfo;
15 | import org.apache.shiro.authz.AuthorizationInfo;
16 | import org.apache.shiro.authz.SimpleAuthorizationInfo;
17 | import org.apache.shiro.realm.AuthorizingRealm;
18 | import org.apache.shiro.subject.PrincipalCollection;
19 |
20 | import javax.annotation.Resource;
21 | import java.io.Serializable;
22 | import java.util.HashSet;
23 | import java.util.Set;
24 |
25 | /**
26 | * @author : Civism
27 | * @projectName : civism-sso
28 | * @E-mail : 695234456@qq.com
29 | */
30 | public class CivismShiroUpmsRealm extends AuthorizingRealm {
31 |
32 |
33 | @Resource
34 | private SsoUserService ssoUserService;
35 |
36 | @Resource
37 | private RedisClient redisClient;
38 |
39 | @Override
40 | protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
41 | UserInfo userInfo = (UserInfo) principalCollection.getPrimaryPrincipal();
42 |
43 | //根据用户查询有数据接口权限
44 | SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
45 | Set urlSet = new HashSet<>();
46 | urlSet.add("/sso/auth");
47 | info.setStringPermissions(urlSet);
48 |
49 | // info.setRoles(Sets.newHashSet("admin"));
50 | return info;
51 | }
52 |
53 | @Override
54 | protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
55 |
56 |
57 | Object principal = authenticationToken.getPrincipal();
58 |
59 | SsoUserDO ssoUserDO = ssoUserService.queryUserByUserName((String) principal);
60 | if (ssoUserDO == null) {
61 | throw new CustomException(CustomExceptionEnum.ACCOUNT_PASSWORD_ERROR);
62 | }
63 |
64 | Serializable token = SecurityUtils.getSubject().getSession().getId();
65 |
66 | UserInfo userInfo = UserInfo.builder().name(ssoUserDO.getName())
67 | .token((String) token).id(ssoUserDO.getId()).build();
68 | redisClient.set((String) token, userInfo, CivismConstant.EXPIRE);
69 | return new SimpleAuthenticationInfo(userInfo, ssoUserDO.getPassword(),
70 | getName());
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/shiro/CustomRolePermissionResolver.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.shiro;
2 |
3 | import org.apache.shiro.authz.Permission;
4 | import org.apache.shiro.authz.permission.RolePermissionResolver;
5 |
6 | import java.util.Collection;
7 | import java.util.LinkedList;
8 | import java.util.List;
9 |
10 | /**
11 | * @author : Civism
12 | * @version 1.0
13 | * @projectName:civism-sso
14 | * @Time: 2020-09-18
15 | * @E-mail:695234456@qq.com
16 | */
17 | public class CustomRolePermissionResolver implements RolePermissionResolver {
18 |
19 | @Override
20 | public Collection resolvePermissionsInRole(String s) {
21 |
22 |
23 |
24 | List roleList = new LinkedList<>();
25 | roleList.add(new RolePermission(s));
26 | return roleList;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/shiro/JavaUuidSessionIdGenerator.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.shiro;
2 |
3 | import org.apache.shiro.session.Session;
4 | import org.apache.shiro.session.mgt.eis.SessionIdGenerator;
5 |
6 | import java.io.Serializable;
7 | import java.util.UUID;
8 |
9 | /**
10 | * @author : Civism
11 | * @projectName : civism-sso
12 | * @E-mail : 695234456@qq.com
13 | */
14 | public class JavaUuidSessionIdGenerator implements SessionIdGenerator {
15 |
16 | public JavaUuidSessionIdGenerator() {
17 | }
18 |
19 |
20 | @Override
21 | public Serializable generateId(Session session) {
22 | return UUID.randomUUID().toString().replaceAll("-", "");
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/shiro/RolePermission.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.shiro;
2 |
3 | import org.apache.shiro.authz.Permission;
4 |
5 | /**
6 | * @author : Civism
7 | * @version 1.0
8 | * @projectName:civism-sso
9 | * @Time: 2020-09-18
10 | * @E-mail:695234456@qq.com
11 | */
12 | public class RolePermission implements Permission {
13 |
14 | private String role;
15 |
16 |
17 | public RolePermission(String role) {
18 | this.role = role;
19 | }
20 |
21 | @Override
22 | public boolean implies(Permission permission) {
23 |
24 | return false;
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/shiro/ShiroRedisCacheSessionDAO.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.shiro;
2 |
3 | import com.civism.sso.redis.RedisClient;
4 | import org.apache.shiro.session.Session;
5 | import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
6 |
7 | import javax.annotation.Resource;
8 | import java.io.Serializable;
9 |
10 | /**
11 | * @author : Civism
12 | * @projectName : civism-sso
13 | * @E-mail : 695234456@qq.com
14 | */
15 | public class ShiroRedisCacheSessionDAO extends EnterpriseCacheSessionDAO {
16 |
17 |
18 | private static final String REDIS_KEY = "civism-sso-redis-";
19 |
20 | @Resource
21 | private RedisClient redisClient;
22 |
23 | @Override
24 | protected Serializable doCreate(Session session) {
25 |
26 | Serializable serializable = super.doCreate(session);
27 | redisClient.set(REDIS_KEY + serializable, session, (int) session.getTimeout() / 1000);
28 | return serializable;
29 | }
30 |
31 | @Override
32 | protected Session doReadSession(Serializable sessionId) {
33 | Session session = super.doReadSession(sessionId);
34 | if (session == null) {
35 | session = (Session) redisClient.get(REDIS_KEY + sessionId);
36 | }
37 | return session;
38 | }
39 |
40 | @Override
41 | protected void doUpdate(Session session) {
42 | super.doUpdate(session);
43 | redisClient.set(REDIS_KEY + session.getId(), session, (int) session.getTimeout() / 1000);
44 | }
45 |
46 | @Override
47 | protected void doDelete(Session session) {
48 | super.doDelete(session);
49 | redisClient.delete(REDIS_KEY + session.getId());
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/shiro/ShiroSessionManager.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.shiro;
2 |
3 | import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
4 |
5 | import javax.servlet.ServletRequest;
6 | import javax.servlet.ServletResponse;
7 | import javax.servlet.http.HttpServletRequest;
8 | import java.io.Serializable;
9 |
10 |
11 | /**
12 | * @author : Civism
13 | * @projectName : civism-sso
14 | * @E-mail : 695234456@qq.com
15 | */
16 | public class ShiroSessionManager extends DefaultWebSessionManager {
17 |
18 |
19 | @Override
20 | protected Serializable getSessionId(ServletRequest httpRequest, ServletResponse response) {
21 | HttpServletRequest request = (HttpServletRequest) httpRequest;
22 | return request.getHeader("token");
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/shiro/UrlPathMatcher.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.shiro;
2 |
3 | import org.apache.shiro.util.PatternMatcher;
4 |
5 | import java.util.regex.Matcher;
6 | import java.util.regex.Pattern;
7 |
8 | /**
9 | * @author : Civism
10 | * @projectName : civism-sso
11 | * @E-mail : 695234456@qq.com
12 | */
13 | public class UrlPathMatcher implements PatternMatcher {
14 |
15 | @Override
16 | public boolean matches(String p, String source) {
17 | if (p.equals(source)) {
18 | return true;
19 | } else {
20 | //原始路径, source请求路径
21 | Pattern pattern = Pattern.compile(p);
22 | Matcher matcher = pattern.matcher(source);
23 | return matcher.matches();
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/shiro/UrlPermission.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.shiro;
2 |
3 | import org.apache.shiro.authz.Permission;
4 | import org.apache.shiro.util.PatternMatcher;
5 |
6 | /**
7 | * @author : Civism
8 | * @projectName : civism-sso
9 | * @E-mail : 695234456@qq.com
10 | */
11 | public class UrlPermission implements Permission {
12 |
13 |
14 | private String url;
15 |
16 | public UrlPermission(String url) {
17 | this.url = url;
18 | }
19 |
20 | @Override
21 | public boolean implies(Permission p) {
22 | if (!(p instanceof UrlPermission)) {
23 | return false;
24 | }
25 | UrlPermission urlPermission = (UrlPermission) p;
26 | PatternMatcher patternMatcher = new UrlPathMatcher();
27 | return patternMatcher.matches(this.url, urlPermission.url);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/com/civism/sso/shiro/UrlPermissionResolver.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso.shiro;
2 |
3 | import org.apache.shiro.authz.Permission;
4 | import org.apache.shiro.authz.permission.PermissionResolver;
5 |
6 | /**
7 | * @author : Civism
8 | * @projectName : civism-sso
9 | * @E-mail : 695234456@qq.com
10 | */
11 | public class UrlPermissionResolver implements PermissionResolver {
12 | @Override
13 | public Permission resolvePermission(String permissionString) {
14 | return new UrlPermission(permissionString);
15 | }
16 | }
--------------------------------------------------------------------------------
/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8081
3 | spring:
4 | http:
5 | encoding:
6 | charset: UTF-8
7 | force: true
8 | enabled: true
9 | datasource:
10 | url: jdbc:mysql://127.0.0.1:3306/civism-sso?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&useSSL=false
11 | username: root
12 | password: 123456
13 | type: com.alibaba.druid.pool.DruidDataSource
14 | filters: stat
15 | maxActive: 20
16 | initialSize: 1
17 | maxWait: 60000
18 | minIdle: 1
19 | timeBetweenEvictionRunsMillis: 60000
20 | minEvictableIdleTimeMillis: 300000
21 | validationQuery: select 'x'
22 | testWhileIdle: true
23 | testOnBorrow: false
24 | testOnReturn: false
25 | poolPreparedStatements: true
26 | maxOpenPreparedStatements: 20
27 | main:
28 | allow-bean-definition-overriding: true
29 | jackson:
30 | default-property-inclusion: non_null
31 | date-format: yyyy-MM-dd HH:mm:ss
32 | servlet:
33 | multipart:
34 | max-file-size: 2MB
35 | max-request-size: 10MB
36 | redis:
37 | host: 127.0.0.1
38 | port: 6379
39 | password:
40 | aop:
41 | proxy-target-class: true
42 |
43 | ## 该配置节点为独立的节点,有很多同学容易将这个配置放在spring的节点下,导致配置无法被识别
44 | mybatis:
45 | mapper-locations: classpath*:mapper/*.xml #注意:一定要对应mapper映射xml文件的所在路径
46 | type-aliases-package: com.civism.sso.entity # 注意:对应实体类的路径
47 |
48 | #pagehelper分页插件
49 | pagehelper:
50 | helperDialect: mysql
51 | reasonable: false
52 | supportMethodsArguments: true
53 | params: count=countSql
54 | #文档接口
55 | swagger:
56 | enable: true
--------------------------------------------------------------------------------
/src/main/resources/mapper/sso_product.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/src/test/java/com/civism/sso/SsoApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.civism.sso;
2 |
3 | import com.civism.sso.entity.SsoProductDO;
4 | import com.civism.sso.service.SsoProductService;
5 | import com.github.pagehelper.PageHelper;
6 | import com.github.pagehelper.PageInfo;
7 | import org.junit.jupiter.api.Test;
8 | import org.springframework.boot.test.context.SpringBootTest;
9 | import org.springframework.data.redis.core.RedisTemplate;
10 |
11 | import javax.annotation.Resource;
12 | import java.util.List;
13 |
14 | @SpringBootTest
15 | public class SsoApplicationTests {
16 |
17 | @Resource
18 | private SsoProductService ssoProductService;
19 |
20 | @Resource
21 | private RedisTemplate redisTemplate;
22 |
23 | @Test
24 | public void 测试redis() {
25 | redisTemplate.opsForValue().set("star", "123");
26 |
27 | Object star = redisTemplate.opsForValue().get("star");
28 | System.out.println(star);
29 | }
30 |
31 | @Test
32 | void contextLoads() {
33 | PageHelper.startPage(1, 10);
34 | List list = ssoProductService.list();
35 | PageInfo pageInfo = new PageInfo<>(list);
36 |
37 | System.out.println(pageInfo);
38 | }
39 |
40 | }
41 |
--------------------------------------------------------------------------------