Skip to content

Commit 74c125e

Browse files
committedJun 20, 2018
本次更新引入的spring-security用于对前台会员进行登录控制,后台管理仍使用shiro框架,前后台独立登录,不会出现挤掉另一端的BUG
spring-security已与JWT进行了完美的整合(不得不说spring家族的框架比shiro要好处理的太多了) 数据库更新,对前台会员表进行了更新,引入了spring-security最新的密码验证机制BCryptPasswordEncoder,使用随机密钥方式,移除了原有的密码盐方式 修复上次提交时pom文件打包的错误 修复部署文件
1 parent 6a1c07a commit 74c125e

39 files changed

+755
-827
lines changed
 

‎README.md

+32-22
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,30 @@
1-
##更新记录
1+
***
2+
3+
# Geek-Framework 微服务快速开发脚手架
4+
5+
### 平台简介
6+
7+
Geek-Framework是基于多个优秀的开源项目,高度整合封装而成的高效,高性能,强安全性的**开源**Java微服务快速开发框架。
8+
9+
Geek-Framework是在SpringBoot基础上搭建的一个Java基础开发框架,以Spring MVC为模型视图控制器,MyBatis为数据访问层,
10+
Apache Shiro和Spring-Security为权限授权层,Ehcahe、redis或**j2cache**进行缓存。
11+
12+
Geek-Framework主要定位于微应用的开发,已内置后台系统的基础功能,用户管理、角色管理、权限管理、会员管理、日志管理等;前台已经实现用户登录,注册等基础功能。
13+
同时前后台会员实现分表管理,可扩展多角色系统、多权限系统。
14+
采用分层设计、双重验证、提交数据安全编码、密码加密、访问验证、数据权限验证。
15+
使用Maven做项目管理,提高项目的易开发性、扩展性。
16+
17+
18+
###更新日期2018-06-20
19+
本次更新主要解决了前后台不能在同一浏览器登录的问题
20+
* 本次更新引入的spring-security用于对前台会员进行登录控制,后台管理仍使用shiro框架,前后台独立登录,不会出现挤掉另一端的BUG
21+
* spring-security已与JWT进行了完美的整合(不得不说spring家族的框架比shiro要好处理的太多了)
22+
* 数据库更新,对前台会员表进行了更新,引入了spring-security最新的密码验证机制BCryptPasswordEncoder,使用随机密钥方式,移除了原有的密码盐方式
23+
* 文件目录结构进行了优化调整
24+
* 数据库备份文件至data/geekcattle.sql
25+
* 修复上次提交时pom文件打包的错误
26+
* 修复部署文件
27+
228

329
###更新日期2018-06-14
430
更新说明:SpringBootAdmin已正式更名为Geek-Framework
@@ -28,23 +54,6 @@ PS:现有代码中有J2Cache的源代码,原因是因为发现了一个J2Cache
2854

2955
* 优化已知BUG
3056

31-
32-
***
33-
34-
# Geek-Framework 微服务快速开发脚手架
35-
36-
## 平台简介
37-
38-
Geek-Framework是基于多个优秀的开源项目,高度整合封装而成的高效,高性能,强安全性的**开源**Java微服务快速开发框架。
39-
40-
Geek-Framework是在SpringBoot基础上搭建的一个Java基础开发框架,以Spring MVC为模型视图控制器,MyBatis为数据访问层,
41-
Apache Shiro为权限授权层,Ehcahe、redis或**j2cache**进行缓存。
42-
43-
Geek-Framework主要定位于微应用的开发,已内置后台系统的基础功能,用户管理、角色管理、权限管理、会员管理、日志管理等;前台已经实现用户登录,注册等基础功能。
44-
同时前后台会员实现分表管理,可扩展多角色系统、多权限系统。
45-
采用分层设计、双重验证、提交数据安全编码、密码加密、访问验证、数据权限验证。
46-
使用Maven做项目管理,提高项目的易开发性、扩展性。
47-
4857
## 内置功能
4958

5059
1. 管理员管理:管理员是系统操作者,该功能主要完成系统管理员相关配置和角色授权。
@@ -59,7 +68,7 @@ Geek-Framework主要定位于微应用的开发,已内置后台系统的基础
5968

6069
* 核心框架:SpringBoot 2.0.2.RELEASE
6170
* 集成运行框架:Tomcat 8.5.31
62-
* 安全框架:Apache Shiro 1.4
71+
* 安全框架:Apache Shiro 1.4 Spring-Security 5.0.5
6372
* 视图框架:Spring MVC 5.0.6
6473
* 服务端验证:Hibernate Validator 6.0.9
6574
* 布局框架:Thymeleaf 3.0.9
@@ -97,15 +106,16 @@ Geek-Framework主要定位于微应用的开发,已内置后台系统的基础
97106
5. 密码加密:登录用户密码进行SHA1散列加密,此加密方法是不可逆的。保证密文泄露后的安全问题。
98107
6. 强制访问:系统对所有管理端链接都进行用户身份权限验证,防止用户直接填写url进行访问。
99108

100-
## 演示地址
109+
## 账号信息
101110

102-
* <http://www.geekcattle.com/> &nbsp; 用户名:admin 密码:admin
111+
* 后台账号密码:admin ---- admin
112+
* 前台账号密码:guest ---- hao123
103113

104114
PS:测试数据库会不定期恢复。
105115

106116
## 快速体验
107117

108-
1. 具备运行环境:JDK1.7+、Maven3.0+、MySql5+。
118+
1. 具备运行环境:JDK1.8+、Maven3.0+、MySql5+。
109119
2. 修改src\main\resources\application.properties、application-dev.properties、application-pro.properties文件中的数据库设置参数(application-dev.properties为开发环境的相应参数,application-pro.properties为部署环境的相应参数)。
110120
3. 根据修改参数创建对应MySql数据库用户和参数。
111121
4. 运行mvn package脚本,即可创建项目jar文件,同时也可以通过java -jar *.jar 即可本地预览

‎check.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/bin/sh
2-
APP_NAME=spring-boot-admin
2+
APP_NAME=geek-framework
33

44
tpid=`ps -ef|grep $APP_NAME|grep -v grep|grep -v kill|awk '{print $2}'`
55
if [ ${tpid} ]; then

‎data/geekcattle.sql

+138-77
Large diffs are not rendered by default.

‎jwt使用.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@
2121

2222
##3、获取token
2323

24-
登录地址 /api/oauth/token,此处登录验证与用户realm有关,可根据业务需要进行更改
25-
登录成功之后通过jwtUtil.createJWT生成token信息(用户身份信息,过期时间等可自行增加),将token返回给客户端,客户端存储该token
24+
登录地址 /member/login
25+
登录成功之后在AjaxAuthSuccessHandler通过jwtUtil生成token信息(用户身份信息,过期时间等可自行增加),将token返回给客户端,客户端存储该token
2626

2727
##4、客户端增加token
2828

2929
客户端请求时在header里面添加authorization选项,值为Bearer+空格+token(可用postman进行测试)
3030

3131
##5、验证token
3232

33-
token验证是通过filter完成的,filter验证成功之后将解析出的用户信息通过shiro的token功能进行登录,更方便的调用用户信息
33+
token验证是通过JwtAuthenticationFilter完成的,验证成功之后将解析出的用户信息提交给spring-security进行处理登录,以方便在后续的操作中使用
3434

3535

‎pom.xml

+22-5
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
33
<modelVersion>4.0.0</modelVersion>
44
<groupId>com.geekcattle</groupId>
5-
<artifactId>geek-framwork</artifactId>
6-
<packaging>pom</packaging>
5+
<artifactId>geek-framework</artifactId>
6+
<packaging>jar</packaging>
77
<version>2.0-SNAPSHOT</version>
88
<name>Geek-Framework</name>
99
<url>http://www.geekcattle.com</url>
@@ -36,6 +36,8 @@
3636
<mysql.version>5.1.29</mysql.version>
3737
<jackson.version>2.8.5</jackson.version>
3838
<servlet.version>3.0.1</servlet.version>
39+
40+
<springfox-version>2.7.0</springfox-version>
3941
</properties>
4042

4143
<dependencies>
@@ -66,8 +68,6 @@
6668
<artifactId>spring-boot-starter-thymeleaf</artifactId>
6769
</dependency>
6870

69-
70-
7171
<dependency>
7272
<groupId>org.springframework.boot</groupId>
7373
<artifactId>spring-boot-starter-test</artifactId>
@@ -78,11 +78,28 @@
7878
<artifactId>spring-boot-starter-data-redis</artifactId>
7979
</dependency>
8080

81+
<dependency>
82+
<groupId>org.springframework.boot</groupId>
83+
<artifactId>spring-boot-starter-security</artifactId>
84+
</dependency>
85+
8186
<dependency>
8287
<groupId>org.springframework</groupId>
8388
<artifactId>spring-context-support</artifactId>
8489
</dependency>
8590

91+
<!--SpringFox dependencies -->
92+
<dependency>
93+
<groupId>io.springfox</groupId>
94+
<artifactId>springfox-swagger2</artifactId>
95+
<version>${springfox-version}</version>
96+
</dependency>
97+
<dependency>
98+
<groupId>io.springfox</groupId>
99+
<artifactId>springfox-swagger-ui</artifactId>
100+
<version>${springfox-version}</version>
101+
</dependency>
102+
86103
<!-- shiro spring. -->
87104
<dependency>
88105
<groupId>org.apache.shiro</groupId>
@@ -224,7 +241,7 @@
224241
<dependency>
225242
<groupId>org.springframework</groupId>
226243
<artifactId>springloaded</artifactId>
227-
<version>1.2.5.RELEASE</version>
244+
<version>1.2.8.RELEASE</version>
228245
</dependency>
229246
</dependencies>
230247
<configuration>

‎shutdown.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/bin/sh
2-
APP_NAME=spring-boot-admin
2+
APP_NAME=geek-framework
33

44
tpid=`ps -ef|grep $APP_NAME|grep -v grep|grep -v kill|awk '{print $2}'`
55
if [ ${tpid} ]; then

‎src/main/java/com/geekcattle/Application.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,13 @@
66

77
import org.springframework.boot.SpringApplication;
88
import org.springframework.boot.autoconfigure.SpringBootApplication;
9+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
910
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
1011
import org.springframework.transaction.annotation.EnableTransactionManagement;
1112
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
1213

13-
@EnableTransactionManagement // 启注解事务管理
1414
@SpringBootApplication//SpringBoot启动核心
15+
@EnableConfigurationProperties
1516
public class Application {
1617
//启动文件
1718
public static void main(String[] args){

‎src/main/java/com/geekcattle/controller/api/ApiMemberController.java

+5-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.geekcattle.controller.api;
22

3+
import com.geekcattle.core.utils.SecurityUtil;
34
import com.geekcattle.mapper.member.MemberMapper;
45
import com.geekcattle.model.member.Member;
56
import com.geekcattle.util.ReturnUtil;
@@ -9,6 +10,7 @@
910
import org.apache.shiro.subject.Subject;
1011
import org.slf4j.Logger;
1112
import org.slf4j.LoggerFactory;
13+
import org.springframework.security.core.userdetails.User;
1214
import org.springframework.ui.ModelMap;
1315
import org.springframework.web.bind.annotation.RequestMapping;
1416
import org.springframework.web.bind.annotation.RequestMethod;
@@ -23,17 +25,11 @@ public class ApiMemberController {
2325

2426
protected Logger logger = LoggerFactory.getLogger(this.getClass());
2527

26-
@Resource
27-
private MemberMapper memberMapper;
28-
29-
3028
@RequestMapping(value = "/index", method = RequestMethod.GET)
3129
public ModelMap index(){
32-
Subject subject = SecurityUtils.getSubject();
33-
if(subject.isAuthenticated()){
34-
PrincipalCollection principals = subject.getPrincipals();
35-
Member member = (Member) principals.getPrimaryPrincipal();
36-
return ReturnUtil.Success("获取用户信息成功", member);
30+
if(SecurityUtil.isLogin()){
31+
User user = SecurityUtil.getFontUserInfo();
32+
return ReturnUtil.Success("获取用户信息成功", user);
3733
}else{
3834
return ReturnUtil.Error("用户不存在");
3935
}

‎src/main/java/com/geekcattle/controller/api/ApiPublicController.java

-117
This file was deleted.

‎src/main/java/com/geekcattle/controller/console/MainController.java

+5-5
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44

55
package com.geekcattle.controller.console;
66

7-
import com.geekcattle.core.shiro.AdminShiroUtil;
7+
import com.geekcattle.core.utils.ShiroUtil;
88
import com.geekcattle.model.console.Admin;
99
import com.geekcattle.model.console.Menu;
1010
import com.geekcattle.model.console.Role;
1111
import com.geekcattle.service.console.*;
1212
import com.geekcattle.util.ReturnUtil;
13-
import com.geekcattle.util.console.MenuTreeUtil;
13+
import com.geekcattle.model.console.MenuTree;
1414
import org.slf4j.Logger;
1515
import org.slf4j.LoggerFactory;
1616
import org.springframework.beans.factory.annotation.Autowired;
@@ -43,7 +43,7 @@ public class MainController {
4343

4444
@RequestMapping(value = "/index", method = {RequestMethod.GET})
4545
public String index(Model model) {
46-
Admin admin = AdminShiroUtil.getUserInfo();
46+
Admin admin = ShiroUtil.getUserInfo();
4747
List<Menu> treeGridList = this.getMenu(admin);
4848
model.addAttribute("admin", admin);
4949
model.addAttribute("menuLists", treeGridList);
@@ -54,7 +54,7 @@ public String index(Model model) {
5454
@ResponseBody
5555
public ModelMap wapper() {
5656
try {
57-
Admin admin = AdminShiroUtil.getUserInfo();
57+
Admin admin = ShiroUtil.getUserInfo();
5858
List<Menu> treeGridList = this.getMenu(admin);
5959
ModelMap mp = new ModelMap();
6060
mp.put("admin", admin);
@@ -73,7 +73,7 @@ private List<Menu> getMenu(Admin admin) {
7373
}else{
7474
menuLists = menuService.selectMenuByAdminId(admin.getUid());
7575
}
76-
MenuTreeUtil menuTreeUtil = new MenuTreeUtil(menuLists,null);
76+
MenuTree menuTreeUtil = new MenuTree(menuLists,null);
7777
return menuTreeUtil.buildTreeGrid();
7878
}
7979

‎src/main/java/com/geekcattle/controller/console/MenuController.java

+2-8
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,15 @@
44

55
package com.geekcattle.controller.console;
66

7-
import com.geekcattle.model.console.Admin;
8-
import com.geekcattle.model.console.AdminRole;
97
import com.geekcattle.model.console.Menu;
10-
import com.geekcattle.model.console.Role;
118
import com.geekcattle.service.console.*;
129
import com.geekcattle.util.DateUtil;
13-
import com.geekcattle.util.PasswordUtil;
1410
import com.geekcattle.util.ReturnUtil;
1511
import com.geekcattle.util.UuidUtil;
16-
import com.geekcattle.util.console.MenuTreeUtil;
17-
import com.github.pagehelper.PageInfo;
12+
import com.geekcattle.model.console.MenuTree;
1813
import org.apache.commons.lang3.StringUtils;
1914
import org.apache.shiro.authz.annotation.RequiresAuthentication;
2015
import org.apache.shiro.authz.annotation.RequiresPermissions;
21-
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
2216
import org.slf4j.Logger;
2317
import org.slf4j.LoggerFactory;
2418
import org.springframework.beans.factory.annotation.Autowired;
@@ -69,7 +63,7 @@ public String index(Model model) {
6963
public ModelMap list() {
7064
ModelMap map = new ModelMap();
7165
List<Menu> List = menuService.getMenuAll();
72-
MenuTreeUtil menuTreeUtil = new MenuTreeUtil(List, null);
66+
MenuTree menuTreeUtil = new MenuTree(List, null);
7367
List<Menu> treeGridList = menuTreeUtil.buildTreeGrid();
7468
map.put("treeList", treeGridList);
7569
map.put("total", List.size());

‎src/main/java/com/geekcattle/controller/console/PublicController.java

+3-13
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
import com.geekcattle.core.LoginEnum;
88
import com.geekcattle.core.shiro.CustomerAuthenticationToken;
9+
import com.geekcattle.core.utils.ShiroUtil;
910
import com.geekcattle.model.valid.ValidAdmin;
1011
import com.geekcattle.service.console.LogService;
1112
import com.geekcattle.util.IpUtil;
@@ -36,13 +37,8 @@ public class PublicController {
3637

3738
@RequestMapping(value="/login", method=RequestMethod.GET)
3839
public String loginForm(){
39-
try {
40-
Boolean isAuth = SecurityUtils.getSubject().isAuthenticated();
41-
if(isAuth){
42-
return "redirect:/console/index";
43-
}
44-
}catch (Exception e){
45-
e.printStackTrace();
40+
if(ShiroUtil.isLogin()){
41+
return "redirect:/console/index";
4642
}
4743
return "console/login";
4844
}
@@ -105,10 +101,4 @@ public String logout(RedirectAttributes redirectAttributes ){
105101
return "redirect:/console/login";
106102
}
107103

108-
@RequestMapping("/403")
109-
public String unauthorizedRole(){
110-
logger.info("------没有权限-------");
111-
return "403";
112-
}
113-
114104
}

‎src/main/java/com/geekcattle/controller/console/RoleController.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
import com.geekcattle.util.DateUtil;
1313
import com.geekcattle.util.ReturnUtil;
1414
import com.geekcattle.util.UuidUtil;
15-
import com.geekcattle.util.console.MenuTreeUtil;
15+
import com.geekcattle.model.console.MenuTree;
1616
import com.github.pagehelper.PageInfo;
1717
import org.apache.commons.lang3.StringUtils;
1818
import org.apache.shiro.authz.annotation.RequiresPermissions;
@@ -145,7 +145,7 @@ public ModelMap comboTree(String id) {
145145
RoleMenu roleMenu = new RoleMenu();
146146
roleMenu.setRoleId(id);
147147
List<RoleMenu> roleMenuLists = roleMenuService.getRoleList(roleMenu);
148-
MenuTreeUtil menuTreeUtil = new MenuTreeUtil(menuLists, roleMenuLists);
148+
MenuTree menuTreeUtil = new MenuTree(menuLists, roleMenuLists);
149149
List<Map<String, Object>> mapList = menuTreeUtil.buildTree();
150150
return ReturnUtil.Success(null, mapList, null);
151151
}

‎src/main/java/com/geekcattle/controller/member/HomeController.java

+18-50
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,17 @@
44

55
package com.geekcattle.controller.member;
66

7-
import com.geekcattle.model.member.Member;
8-
import org.apache.shiro.SecurityUtils;
9-
import org.apache.shiro.cache.Cache;
10-
import org.apache.shiro.subject.PrincipalCollection;
11-
import org.apache.shiro.subject.Subject;
7+
import com.geekcattle.core.utils.SecurityUtil;
128
import org.slf4j.Logger;
139
import org.slf4j.LoggerFactory;
10+
import org.springframework.security.core.context.SecurityContext;
11+
import org.springframework.security.core.context.SecurityContextHolder;
12+
import org.springframework.security.core.userdetails.User;
1413
import org.springframework.stereotype.Controller;
1514
import org.springframework.ui.Model;
1615
import org.springframework.web.bind.annotation.RequestMapping;
1716
import org.springframework.web.bind.annotation.RequestMethod;
1817

19-
import java.util.Collection;
20-
import java.util.concurrent.ConcurrentHashMap;
21-
import java.util.concurrent.ConcurrentMap;
22-
2318

2419
/**
2520
* author geekcattle
@@ -31,38 +26,19 @@ public class HomeController {
3126

3227
protected Logger logger = LoggerFactory.getLogger(this.getClass());
3328

34-
private ConcurrentMap<String, Cache> caches;
35-
36-
public HomeController() {
37-
this.caches = new ConcurrentHashMap<String, Cache>();
29+
@RequestMapping
30+
public String empty(){
31+
return "redirect:/member/index";
3832
}
3933

4034
@RequestMapping("/index")
4135
public String index(Model model){
42-
Subject subject = SecurityUtils.getSubject();
43-
PrincipalCollection principals = subject.getPrincipals();
44-
Member member = (Member) principals.getPrimaryPrincipal();
45-
String account = member.getAccount();
46-
model.addAttribute("account", account);
47-
48-
49-
Collection<Cache> values = caches.values();
50-
StringBuilder sb = new StringBuilder(getClass().getSimpleName())
51-
.append(" with ")
52-
.append(caches.size())
53-
.append(" cache(s)): [");
54-
int i = 0;
55-
for (Cache cache : values) {
56-
if (i > 0) {
57-
sb.append(", ");
58-
}
59-
sb.append(cache.toString());
60-
i++;
36+
String account = "";
37+
if(SecurityUtil.isLogin()){
38+
User user = SecurityUtil.getFontUserInfo();
39+
account = user.getUsername();
6140
}
62-
sb.append("]");
63-
64-
System.out.println(sb.toString());
65-
41+
model.addAttribute("account", account);
6642
return "member/home";
6743
}
6844

@@ -72,13 +48,9 @@ public String index(Model model){
7248
*/
7349
@RequestMapping(value = "/login", method = RequestMethod.GET)
7450
public String login(){
75-
try {
76-
Boolean isAuth = SecurityUtils.getSubject().isAuthenticated();
77-
if(isAuth){
78-
return "redirect:/member/index";
79-
}
80-
}catch (Exception e){
81-
e.printStackTrace();
51+
SecurityContext securityContext = SecurityContextHolder.getContext();
52+
if(SecurityUtil.isLogin()){
53+
return "redirect:/member/index";
8254
}
8355
return "member/login";
8456
}
@@ -89,13 +61,9 @@ public String login(){
8961
*/
9062
@RequestMapping(value = "/reg", method = RequestMethod.GET)
9163
public String reg(){
92-
try {
93-
Boolean isAuth = SecurityUtils.getSubject().isAuthenticated();
94-
if(isAuth){
95-
return "redirect:/member/index";
96-
}
97-
}catch (Exception e){
98-
e.printStackTrace();
64+
SecurityContext securityContext = SecurityUtil.getContext();
65+
if(SecurityUtil.isLogin()){
66+
return "redirect:/member/index";
9967
}
10068
return "member/reg";
10169
}

‎src/main/java/com/geekcattle/controller/member/MemberController.java

+3-54
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import org.slf4j.Logger;
2323
import org.slf4j.LoggerFactory;
2424
import org.springframework.beans.factory.annotation.Autowired;
25+
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
2526
import org.springframework.ui.ModelMap;
2627
import org.springframework.validation.BindingResult;
2728
import org.springframework.web.bind.annotation.RequestMapping;
@@ -45,57 +46,6 @@ public class MemberController {
4546
@Autowired
4647
private MemberService memberService;
4748

48-
/**
49-
* 处理注册操作
50-
*
51-
* @param validMember
52-
* @param bindingResult
53-
* @param redirectAttributes
54-
* @return string
55-
*/
56-
@RequestMapping(value = "/login", method = RequestMethod.POST)
57-
public ModelMap doLogin(@Valid ValidMember validMember, BindingResult bindingResult, RedirectAttributes redirectAttributes) {
58-
if (bindingResult.hasErrors()) {
59-
return ReturnUtil.Error("用户名或密码为空", null, null);
60-
}
61-
String username = validMember.getAccount();
62-
CustomerAuthenticationToken token = new CustomerAuthenticationToken(validMember.getAccount(), validMember.getPassword(), false);
63-
token.setLoginType(LoginEnum.CUSTOMER.toString());
64-
//获取当前的Subject
65-
Subject currentUser = SecurityUtils.getSubject();
66-
try {
67-
logger.info("对用户[" + username + "]进行登录验证..验证开始");
68-
currentUser.login(token);
69-
logger.info("对用户[" + username + "]进行登录验证..验证通过");
70-
} catch (UnknownAccountException uae) {
71-
logger.info("对用户[" + username + "]进行登录验证..验证未通过,未知账户");
72-
redirectAttributes.addFlashAttribute("message", "未知账户");
73-
} catch (IncorrectCredentialsException ice) {
74-
logger.info("对用户[" + username + "]进行登录验证..验证未通过,错误的凭证");
75-
redirectAttributes.addFlashAttribute("message", "密码不正确");
76-
} catch (LockedAccountException lae) {
77-
logger.info("对用户[" + username + "]进行登录验证..验证未通过,账户已锁定");
78-
redirectAttributes.addFlashAttribute("message", "账户已锁定");
79-
} catch (ExcessiveAttemptsException eae) {
80-
logger.info("对用户[" + username + "]进行登录验证..验证未通过,错误次数过多");
81-
redirectAttributes.addFlashAttribute("message", "用户名或密码错误次数过多");
82-
} catch (AuthenticationException ae) {
83-
logger.info("对用户[" + username + "]进行登录验证..验证未通过,堆栈轨迹如下");
84-
ae.printStackTrace();
85-
redirectAttributes.addFlashAttribute("message", "用户名或密码不正确");
86-
}
87-
//验证是否登录成功
88-
if (currentUser.isAuthenticated()) {
89-
Session session = currentUser.getSession();
90-
session.setAttribute("loginType", LoginEnum.CUSTOMER.toString());
91-
logger.info("前台用户[" + username + "]登录认证通过");
92-
return ReturnUtil.Success("登录成功");
93-
} else {
94-
token.clear();
95-
return ReturnUtil.Error("登录失败", null, null);
96-
}
97-
}
98-
9949
/**
10050
* 处理登录操作
10151
*
@@ -120,9 +70,8 @@ public ModelMap doReg(@Valid Member member, BindingResult bindingResult) {
12070
}
12171
String Id = UuidUtil.getUUID();
12272
member.setUid(Id);
123-
String salt = new SecureRandomNumberGenerator().nextBytes().toHex();
124-
member.setSalt(salt);
125-
String password = PasswordUtil.createCustomPwd(member.getPassword(), member.getSalt());
73+
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
74+
String password = passwordEncoder.encode(member.getPassword());
12675
member.setPassword(password);
12776
member.setState(1);
12877
member.setCreatedAt(DateUtil.getCurrentTime());

‎src/main/java/com/geekcattle/core/filter/JwtFilter.java

-65
This file was deleted.

‎src/main/java/com/geekcattle/core/jwt/JwtShiroRealm.java

-129
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.geekcattle.core.security;
2+
3+
import com.geekcattle.util.JsonUtil;
4+
import org.springframework.security.core.AuthenticationException;
5+
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
6+
7+
import javax.servlet.ServletException;
8+
import javax.servlet.http.HttpServletRequest;
9+
import javax.servlet.http.HttpServletResponse;
10+
import java.io.IOException;
11+
import java.util.HashMap;
12+
import java.util.Map;
13+
14+
public class AjaxAuthFailHandler extends SimpleUrlAuthenticationFailureHandler {
15+
16+
@Override
17+
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
18+
if(isAjaxRequest(request)){
19+
response.setStatus(HttpServletResponse.SC_OK);
20+
response.setContentType("text/json;charset=utf-8");
21+
Map<String,Object> mp = new HashMap<String, Object>();
22+
response.getWriter().print(JsonUtil.toJsonError("登录失败",exception.getMessage()));
23+
response.getWriter().flush();
24+
}else{
25+
super.onAuthenticationFailure(request, response, exception);
26+
}
27+
}
28+
29+
public static boolean isAjaxRequest(HttpServletRequest request) {
30+
String ajaxFlag = request.getHeader("X-Requested-With");
31+
return ajaxFlag != null && "XMLHttpRequest".equals(ajaxFlag);
32+
}
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
package com.geekcattle.core.security;
2+
3+
import com.geekcattle.core.security.jwt.JwtUtil;
4+
import com.geekcattle.util.JsonUtil;
5+
import org.springframework.beans.factory.annotation.Autowired;
6+
import org.springframework.security.core.Authentication;
7+
import org.springframework.security.core.userdetails.User;
8+
import org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler;
9+
10+
import javax.servlet.ServletException;
11+
import javax.servlet.http.HttpServletRequest;
12+
import javax.servlet.http.HttpServletResponse;
13+
import java.io.IOException;
14+
import java.util.HashMap;
15+
import java.util.Map;
16+
17+
public class AjaxAuthSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
18+
19+
@Autowired
20+
private JwtUtil jwtUtil;
21+
22+
public AjaxAuthSuccessHandler(JwtUtil jwtUtil){
23+
this.jwtUtil = jwtUtil;
24+
}
25+
26+
@Override
27+
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
28+
if(isAjaxRequest(request)) {
29+
response.setStatus(HttpServletResponse.SC_OK);
30+
response.setContentType("application/json;charset=utf-8");
31+
CustomUser user = (CustomUser) authentication.getPrincipal();
32+
String accessToken = jwtUtil.generateAccessToken(user);
33+
String refreshToken = jwtUtil.generateRefreshToken(user);
34+
Map<String,Object> mp = new HashMap<String, Object>();
35+
mp.put("access_token", accessToken);
36+
mp.put("refresh_token", refreshToken);
37+
response.getWriter().print(JsonUtil.toJsonSuccess("登录成功",mp));
38+
response.getWriter().flush();
39+
}else{
40+
super.onAuthenticationSuccess(request, response, authentication);
41+
}
42+
}
43+
44+
public static boolean isAjaxRequest(HttpServletRequest request) {
45+
String ajaxFlag = request.getHeader("X-Requested-With");
46+
return ajaxFlag != null && "XMLHttpRequest".equals(ajaxFlag);
47+
}
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package com.geekcattle.core.security;
2+
3+
import org.springframework.security.core.GrantedAuthority;
4+
import org.springframework.security.core.userdetails.User;
5+
6+
import java.util.Collection;
7+
8+
public class CustomUser extends User {
9+
10+
private String uid;
11+
12+
13+
14+
public CustomUser(String uid, String username, String password, Collection<? extends GrantedAuthority> authorities) {
15+
this(uid,username, password, true, true, true, true, authorities);
16+
}
17+
18+
public CustomUser(String uid, String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
19+
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
20+
this.uid = uid;
21+
}
22+
23+
public String getUid() {
24+
return uid;
25+
}
26+
27+
public void setUid(String uid) {
28+
this.uid = uid;
29+
}
30+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.geekcattle.core.security;
2+
3+
import com.geekcattle.model.member.Member;
4+
import com.geekcattle.service.member.MemberService;
5+
import org.springframework.beans.factory.annotation.Autowired;
6+
import org.springframework.security.core.userdetails.UserDetails;
7+
import org.springframework.security.core.userdetails.UserDetailsService;
8+
import org.springframework.security.core.userdetails.UsernameNotFoundException;
9+
import org.springframework.stereotype.Component;
10+
11+
@Component
12+
public class CustomUserDetailsService implements UserDetailsService {
13+
14+
@Autowired
15+
private MemberService memberService;
16+
17+
@Override
18+
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
19+
20+
Member member = memberService.findByUsername(userName);
21+
if(member == null){
22+
throw new UsernameNotFoundException("userName" + userName+"not found");
23+
}
24+
25+
return new CustomUser(member.getUid(), member.getAccount(), member.getPassword(), member.getAuthorities());
26+
}
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package com.geekcattle.core.security;
2+
3+
import com.geekcattle.core.security.jwt.JwtAuthenticationFilter;
4+
import com.geekcattle.core.security.jwt.JwtUtil;
5+
import org.springframework.beans.factory.annotation.Autowired;
6+
import org.springframework.context.annotation.Bean;
7+
import org.springframework.context.annotation.Configuration;
8+
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
9+
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
10+
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
11+
import org.springframework.security.config.annotation.web.builders.WebSecurity;
12+
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
13+
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
14+
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
15+
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
16+
import org.springframework.security.web.firewall.HttpFirewall;
17+
import org.springframework.security.web.firewall.StrictHttpFirewall;
18+
19+
import javax.annotation.Resource;
20+
21+
@Configuration
22+
@EnableWebSecurity
23+
@EnableGlobalMethodSecurity(prePostEnabled = true)//开启security注解
24+
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
25+
26+
@Resource
27+
private CustomUserDetailsService userDetailsService;
28+
29+
@Autowired
30+
private JwtUtil jwtUtil;
31+
32+
@Override
33+
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
34+
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
35+
}
36+
37+
/**
38+
* 配置WebSecurity配置
39+
* @param web
40+
* @throws Exception
41+
*/
42+
@Override
43+
public void configure(WebSecurity web) throws Exception {
44+
super.configure(web);
45+
web.httpFirewall(allowUrlEncodedSlashHttpFirewall());
46+
}
47+
48+
/**
49+
* 开启防火墙对URL分号的处理
50+
* @return
51+
*/
52+
@Bean
53+
public HttpFirewall allowUrlEncodedSlashHttpFirewall() {
54+
StrictHttpFirewall firewall = new StrictHttpFirewall();
55+
firewall.setAllowSemicolon(true);
56+
return firewall;
57+
}
58+
59+
/**
60+
* 配置访问策略
61+
* @param http
62+
* @throws Exception
63+
*/
64+
@Override
65+
protected void configure(HttpSecurity http) throws Exception {
66+
http.authorizeRequests()
67+
//注册端口开启
68+
.antMatchers("/member/reg","/api/**").permitAll()
69+
//会员中心的相关操作必需登录才可访问
70+
.antMatchers("/member/**","/api/member/**").authenticated()
71+
//浏览器报错 x-frame-options deny 的错误
72+
.and().headers().frameOptions().disable()
73+
//登录页面设置
74+
.and().formLogin().loginPage("/member/login").defaultSuccessUrl("/member/index").failureUrl("/member/login?error").usernameParameter("account").passwordParameter("password")
75+
.successHandler(new AjaxAuthSuccessHandler(jwtUtil)).failureHandler(new AjaxAuthFailHandler()).permitAll()
76+
//退出操作设置
77+
.and().logout().logoutUrl("/member/logout").logoutSuccessUrl("/").permitAll();
78+
http.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
79+
//关闭csrf 防止循环定向
80+
http.csrf().disable();
81+
}
82+
83+
84+
@Bean
85+
public JwtAuthenticationFilter jwtAuthenticationFilter(){
86+
return new JwtAuthenticationFilter();
87+
}
88+
89+
90+
91+
}

‎src/main/java/com/geekcattle/core/jwt/AccessToken.java ‎src/main/java/com/geekcattle/core/security/jwt/AccessToken.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.geekcattle.core.jwt;
1+
package com.geekcattle.core.security.jwt;
22

33
public class AccessToken {
44

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.geekcattle.core.security.jwt;
2+
3+
import com.geekcattle.core.security.CustomUser;
4+
import com.geekcattle.core.security.CustomUserDetailsService;
5+
import org.slf4j.Logger;
6+
import org.slf4j.LoggerFactory;
7+
import org.springframework.beans.factory.annotation.Autowired;
8+
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
9+
import org.springframework.security.core.context.SecurityContextHolder;
10+
import org.springframework.security.core.userdetails.User;
11+
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
12+
import org.springframework.web.filter.OncePerRequestFilter;
13+
14+
import javax.servlet.*;
15+
import javax.servlet.http.HttpServletRequest;
16+
import javax.servlet.http.HttpServletResponse;
17+
import java.io.IOException;
18+
19+
public class JwtAuthenticationFilter extends OncePerRequestFilter {
20+
21+
private Logger logger = LoggerFactory.getLogger(this.getClass());
22+
23+
@Autowired
24+
private CustomUserDetailsService userDetailsService;
25+
26+
@Autowired
27+
private JwtConfig jwtConfig;
28+
29+
@Autowired
30+
private JwtUtil jwtUtil;
31+
32+
@Override
33+
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
34+
String authHeader = request.getHeader(jwtConfig.getJwtHeader());
35+
if (authHeader != null && authHeader.startsWith(jwtConfig.getTokenHead())) {
36+
final String authToken = authHeader.substring(jwtConfig.getTokenHead().length());
37+
String username = jwtUtil.getUsernameFromToken(authToken);
38+
39+
logger.info("checking authentication " + username);
40+
41+
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
42+
43+
CustomUser userDetails = (CustomUser)this.userDetailsService.loadUserByUsername(username);
44+
45+
if (jwtUtil.validateToken(authToken, userDetails)) {
46+
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
47+
userDetails, null, userDetails.getAuthorities());
48+
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(
49+
request));
50+
logger.info("authenticated user " + username + ", setting security context");
51+
SecurityContextHolder.getContext().setAuthentication(authentication);
52+
}
53+
}
54+
}
55+
56+
filterChain.doFilter(request, response);
57+
}
58+
}

‎src/main/java/com/geekcattle/core/jwt/JwtConfig.java ‎src/main/java/com/geekcattle/core/security/jwt/JwtConfig.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.geekcattle.core.jwt;
1+
package com.geekcattle.core.security.jwt;
22

33
import org.springframework.beans.factory.annotation.Value;
44
import org.springframework.stereotype.Component;

‎src/main/java/com/geekcattle/core/jwt/JwtUtil.java ‎src/main/java/com/geekcattle/core/security/jwt/JwtUtil.java

+15-49
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,20 @@
1-
package com.geekcattle.core.jwt;
1+
package com.geekcattle.core.security.jwt;
22

3+
import com.geekcattle.core.security.CustomUser;
34
import com.geekcattle.model.member.Member;
45
import com.geekcattle.util.JsonUtil;
56
import com.geekcattle.util.UuidUtil;
67
import io.jsonwebtoken.Claims;
7-
import io.jsonwebtoken.JwtBuilder;
88
import io.jsonwebtoken.Jwts;
99
import io.jsonwebtoken.SignatureAlgorithm;
1010
import io.jsonwebtoken.impl.compression.CompressionCodecs;
1111
import org.slf4j.Logger;
1212
import org.slf4j.LoggerFactory;
1313
import org.springframework.beans.factory.annotation.Autowired;
14+
import org.springframework.security.core.userdetails.User;
1415
import org.springframework.stereotype.Component;
1516

1617

17-
import javax.crypto.spec.SecretKeySpec;
18-
import javax.xml.bind.DatatypeConverter;
19-
import java.security.Key;
2018
import java.util.Date;
2119
import java.util.HashMap;
2220
import java.util.Map;
@@ -38,36 +36,6 @@ public class JwtUtil {
3836
@Autowired
3937
private JwtConfig jwtConfig;
4038

41-
public Claims parseJWT(String jsonWebToken, String base64Security){
42-
try{
43-
Claims claims = Jwts.parser()
44-
.setSigningKey(DatatypeConverter.parseBase64Binary(base64Security))
45-
.parseClaimsJws(jsonWebToken).getBody();
46-
return claims;
47-
}
48-
catch(Exception ex)
49-
{
50-
ex.printStackTrace();
51-
}
52-
return null;
53-
}
54-
55-
public String createJWT(Member member, String base64Security)
56-
{
57-
//生成签名密钥
58-
byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(base64Security);
59-
Key signingKey = new SecretKeySpec(apiKeySecretBytes, SIGNATURE_ALGORITHM.getJcaName());
60-
//添加构成JWT的参数
61-
JwtBuilder builder = Jwts.builder()
62-
.setId(member.getUid())
63-
.setSubject(member.getAccount())
64-
.signWith(SIGNATURE_ALGORITHM, signingKey)
65-
.setExpiration(new Date(System.currentTimeMillis() + jwtConfig.getExpiration()))
66-
.setNotBefore(new Date(System.currentTimeMillis()));
67-
//生成JWT
68-
return builder.compact();
69-
}
70-
7139
public String getUserIdFromToken(String token) {
7240
String userId;
7341
try {
@@ -138,15 +106,15 @@ private Boolean isCreatedBeforeLastPasswordReset(Date created, Date lastPassword
138106
return (lastPasswordReset != null && created.before(lastPasswordReset));
139107
}
140108

141-
public String generateAccessToken(Member member) {
142-
Map<String, Object> claims = generateClaims(member);
143-
return generateAccessToken(member.getAccount(), claims);
109+
public String generateAccessToken(CustomUser user) {
110+
Map<String, Object> claims = generateClaims(user);
111+
return generateAccessToken(user.getUsername(), claims);
144112
}
145113

146-
private Map<String, Object> generateClaims(Member member) {
114+
private Map<String, Object> generateClaims(CustomUser user) {
147115
Map<String, Object> claims = new HashMap<>();
148-
claims.put(CLAIM_KEY_USER_ID, member.getUid());
149-
claims.put(CLAIM_KEY_ACCOUNT_ENABLED, member.getState());
116+
claims.put(CLAIM_KEY_USER_ID, user.getUid());
117+
claims.put(CLAIM_KEY_ACCOUNT_ENABLED, user.isEnabled());
150118
claims.put(CLAIM_KEY_ACCOUNT_NON_LOCKED, false);
151119
claims.put(CLAIM_KEY_ACCOUNT_NON_EXPIRED, false);
152120
return claims;
@@ -156,12 +124,12 @@ private String generateAccessToken(String subject, Map<String, Object> claims) {
156124
return generateToken(subject, claims, jwtConfig.getExpiration());
157125
}
158126

159-
public String generateRefreshToken(Member member) {
160-
Map<String, Object> claims = generateClaims(member);
127+
public String generateRefreshToken(CustomUser user) {
128+
Map<String, Object> claims = generateClaims(user);
161129
// 只授于更新 token 的权限
162130
String roles[] = new String[]{this.ROLE_REFRESH_TOKEN};
163131
claims.put(CLAIM_KEY_AUTHORITIES, JsonUtil.toJson(roles));
164-
return generateRefreshToken(member.getAccount(), claims);
132+
return generateRefreshToken(user.getUsername(), claims);
165133
}
166134

167135
private String generateRefreshToken(String subject, Map<String, Object> claims) {
@@ -197,13 +165,11 @@ private String generateToken(String subject, Map<String, Object> claims, long ex
197165
.compact();
198166
}
199167

200-
public Boolean validateToken(String token, Member member) {
168+
public Boolean validateToken(String token, CustomUser user) {
201169
final String userId = getUserIdFromToken(token);
202170
final String userName = getUsernameFromToken(token);
203-
// final Date created = getCreatedDateFromToken(token);
204-
// final Date expiration = getExpirationDateFromToken(token);
205-
return (userId.equals(member.getUid())
206-
&& userName.equals(member.getAccount())
171+
return (userId.equals(user.getUid())
172+
&& userName.equals(user.getUsername())
207173
&& !isTokenExpired(token)
208174
);
209175
}

‎src/main/java/com/geekcattle/core/shiro/CustomShiroRealm.java

-107
This file was deleted.

‎src/main/java/com/geekcattle/core/filter/CustomerLogoutFilter.java ‎src/main/java/com/geekcattle/core/shiro/CustomerLogoutFilter.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.geekcattle.core.filter;
1+
package com.geekcattle.core.shiro;
22

33
import com.geekcattle.core.redis.RedisCacheManager;
44
import com.geekcattle.core.shiro.AdminShiroRealm;

‎src/main/java/com/geekcattle/core/shiro/ShiroConfiguration.java

+2-47
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,8 @@
66

77
import com.geekcattle.core.j2cache.cache.support.ShiroJ2CacheCacheManager;
88
import com.geekcattle.core.j2cache.cache.support.ShiroJ2CacheSession;
9-
import com.geekcattle.core.jwt.JwtShiroRealm;
109
import com.geekcattle.core.redis.RedisCacheManager;
1110
import com.geekcattle.core.redis.RedisSessionDAO;
12-
import com.geekcattle.core.filter.JwtFilter;
13-
import com.geekcattle.core.filter.CustomerLogoutFilter;
1411
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
1512
import org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy;
1613
import org.apache.shiro.authc.pam.AuthenticationStrategy;
@@ -51,33 +48,6 @@ public class ShiroConfiguration {
5148

5249
private Logger logger = LoggerFactory.getLogger(this.getClass());
5350

54-
/**
55-
* token身份认证realm;
56-
* @return
57-
*/
58-
@Bean(name="jwtShiroRealm")
59-
public JwtShiroRealm jwtShiroRealm(){
60-
logger.debug("ShiroConfiguration.jwtShiroRealm()");
61-
JwtShiroRealm jwtShiroRealm = new JwtShiroRealm();
62-
jwtShiroRealm.setCredentialsMatcher(customHashedCredentialsMatcher());
63-
return new JwtShiroRealm();
64-
}
65-
66-
/**
67-
* 前台身份认证realm;
68-
* @return
69-
*/
70-
@Bean(name="customShiroRealm")
71-
public CustomShiroRealm customShiroRealm(){
72-
logger.debug("ShiroConfiguration.customShiroRealm()");
73-
CustomShiroRealm customShiroRealm = new CustomShiroRealm();
74-
//customShiroRealm.setCacheManager(redisCacheManager());//单redis缓存
75-
customShiroRealm.setCacheManager(shiroJ2CacheCacheManager());//j2cache二级缓存
76-
//redisCacheManager和shiroJ2CacheCacheManager以上两种模式可任选其一,现在默认使用J2Cache
77-
customShiroRealm.setCredentialsMatcher(customHashedCredentialsMatcher());
78-
return customShiroRealm;
79-
}
80-
8151
/**
8252
* 后台身份认证realm;
8353
* @return
@@ -180,12 +150,9 @@ public DefaultWebSecurityManager getDefaultWebSecurityManage(){
180150

181151
Map<String, Object> shiroAuthenticatorRealms = new HashMap<>();
182152
shiroAuthenticatorRealms.put("adminShiroRealm", adminShiroRealm());
183-
shiroAuthenticatorRealms.put("customShiroRealm", customShiroRealm());
184-
shiroAuthenticatorRealms.put("jwtShiroRealm", jwtShiroRealm());
185153

186154
Collection<Realm> shiroAuthorizerRealms = new ArrayList<Realm>();
187155
shiroAuthorizerRealms.add(adminShiroRealm());
188-
shiroAuthorizerRealms.add(customShiroRealm());
189156

190157
CustomModularRealmAuthenticator customModularRealmAuthenticator = new CustomModularRealmAuthenticator();
191158
customModularRealmAuthenticator.setDefinedRealms(shiroAuthenticatorRealms);
@@ -248,9 +215,7 @@ public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityMana
248215
//增加自定义过滤
249216
Map<String, Filter> filters = new HashMap<>();
250217
filters.put("admin", new AdminFormAuthenticationFilter());
251-
filters.put("custom", new CustomFormAuthenticationFilter());
252218
filters.put("logout", new CustomerLogoutFilter());
253-
filters.put("jwt", new JwtFilter());
254219
shiroFilterFactoryBean.setFilters(filters);
255220
//拦截器.
256221
Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();
@@ -273,20 +238,10 @@ public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityMana
273238

274239
//<!-- 过滤链定义,从上向下顺序执行,一般将 /**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
275240
//<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
276-
filterChainDefinitionMap.put("/**/login", "anon");
277-
filterChainDefinitionMap.put("/**/logout", "logout");
278-
filterChainDefinitionMap.put("/**/reg", "anon");
241+
filterChainDefinitionMap.put("/console/login", "anon");
242+
filterChainDefinitionMap.put("/console/logout", "logout");
279243
//配置记住我或认证通过可以访问的地址
280244
filterChainDefinitionMap.put("/console/**", "admin");
281-
filterChainDefinitionMap.put("/member/**", "custom");
282-
283-
filterChainDefinitionMap.put("/api/member/**", "jwt");
284-
// 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
285-
//shiroFilterFactoryBean.setLoginUrl("/member/login");
286-
// 登录成功后要跳转的链接
287-
//shiroFilterFactoryBean.setSuccessUrl("/member/index");
288-
//未授权界面;
289-
//shiroFilterFactoryBean.setUnauthorizedUrl("/console/403");
290245
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
291246
return shiroFilterFactoryBean;
292247
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.geekcattle.core.utils;
2+
3+
import com.geekcattle.model.member.Member;
4+
import org.slf4j.Logger;
5+
import org.slf4j.LoggerFactory;
6+
import org.springframework.security.core.context.SecurityContext;
7+
import org.springframework.security.core.context.SecurityContextHolder;
8+
import org.springframework.security.core.userdetails.User;
9+
10+
public class SecurityUtil {
11+
12+
private Logger logger = LoggerFactory.getLogger(this.getClass());
13+
14+
15+
public static SecurityContext getContext(){
16+
return SecurityContextHolder.getContext();
17+
}
18+
19+
/**
20+
* 判断是否登录
21+
* @return
22+
*/
23+
public static Boolean isLogin(){
24+
return getContext().getAuthentication() != null && getContext().getAuthentication().isAuthenticated() && !getContext().getAuthentication().getName().equals("anonymousUser");
25+
}
26+
27+
/**
28+
* 获取前台用户信息
29+
* @return
30+
*/
31+
public static User getFontUserInfo(){
32+
User user = (User) getContext().getAuthentication().getPrincipal();
33+
return user;
34+
}
35+
36+
}

‎src/main/java/com/geekcattle/core/shiro/AdminShiroUtil.java ‎src/main/java/com/geekcattle/core/utils/ShiroUtil.java

+14-24
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* Copyright (c) 2017 <l_iupeiyu@qq.com> All rights reserved.
33
*/
44

5-
package com.geekcattle.core.shiro;
5+
package com.geekcattle.core.utils;
66

77
import com.geekcattle.model.console.Admin;
88
import org.apache.shiro.SecurityUtils;
@@ -17,7 +17,7 @@
1717
* author geekcattle
1818
* date 2016/12/6 0006 上午 10:45
1919
*/
20-
public class AdminShiroUtil {
20+
public class ShiroUtil {
2121

2222
private Logger logger = LoggerFactory.getLogger(this.getClass());
2323

@@ -28,6 +28,14 @@ public static Subject getSubject(){
2828
return SecurityUtils.getSubject();
2929
}
3030

31+
public static Boolean isLogin(){
32+
return getSubject().isAuthenticated();
33+
}
34+
35+
/**
36+
* 获取session信息
37+
* @return
38+
*/
3139
public static Session getSession(){
3240
try{
3341
Session session = getSubject().getSession();
@@ -43,6 +51,10 @@ public static Session getSession(){
4351
return null;
4452
}
4553

54+
/**
55+
* 获取用户信息
56+
* @return
57+
*/
4658
public static Admin getUserInfo(){
4759
try {
4860
if(getSession() != null){
@@ -56,26 +68,4 @@ public static Admin getUserInfo(){
5668
}
5769
return null;
5870
}
59-
60-
// ============== Shiro Cache ==============
61-
62-
public static Object getCache(String key) {
63-
return getCache(key, null);
64-
}
65-
66-
public static Object getCache(String key, Object defaultValue) {
67-
// Object obj = getCacheMap().get(key);
68-
Object obj = getSession().getAttribute(key);
69-
return obj==null?defaultValue:obj;
70-
}
71-
72-
public static void putCache(String key, Object value) {
73-
// getCacheMap().put(key, value);
74-
getSession().setAttribute(key, value);
75-
}
76-
77-
public static void removeCache(String key) {
78-
// getCacheMap().remove(key);
79-
getSession().removeAttribute(key);
80-
}
8171
}

‎src/main/java/com/geekcattle/util/console/MenuTreeUtil.java ‎src/main/java/com/geekcattle/model/console/MenuTree.java

+3-6
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,8 @@
22
* Copyright (c) 2017 <l_iupeiyu@qq.com> All rights reserved.
33
*/
44

5-
package com.geekcattle.util.console;
5+
package com.geekcattle.model.console;
66

7-
import com.geekcattle.model.console.Menu;
8-
import com.geekcattle.model.console.Role;
9-
import com.geekcattle.model.console.RoleMenu;
107
import org.apache.commons.lang3.StringUtils;
118

129
import java.util.*;
@@ -15,7 +12,7 @@
1512
* author geekcattle
1613
* date 2016/10/21 0021 下午 15:58
1714
*/
18-
public class MenuTreeUtil {
15+
public class MenuTree {
1916

2017
private List<Menu> nodes;
2118

@@ -27,7 +24,7 @@ public class MenuTreeUtil {
2724
*
2825
* @param nodes 将树的所有节点都初始化进来。
2926
*/
30-
public MenuTreeUtil(List<Menu> nodes, List<RoleMenu> checknodes){
27+
public MenuTree(List<Menu> nodes, List<RoleMenu> checknodes){
3128
this.nodes = nodes;
3229
this.checknodes = checknodes;
3330
}

‎src/main/java/com/geekcattle/model/member/Member.java

+39-12
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,23 @@
66

77
import com.fasterxml.jackson.annotation.JsonIgnore;
88
import com.geekcattle.model.BaseEntity;
9+
import org.springframework.security.core.GrantedAuthority;
10+
import org.springframework.security.core.userdetails.User;
11+
import org.springframework.security.core.userdetails.UserDetails;
912

1013
import javax.persistence.Column;
1114
import javax.persistence.GeneratedValue;
1215
import javax.persistence.Id;
1316
import javax.persistence.Transient;
14-
import java.io.Serializable;
17+
import java.util.ArrayList;
18+
import java.util.Collection;
19+
import java.util.List;
1520

1621
/**
1722
* author geekcattle
1823
* date 2016/10/21 0021 下午 15:11
1924
*/
20-
public class Member extends BaseEntity implements Serializable {
25+
public class Member extends BaseEntity implements UserDetails {
2126
@Id
2227
@Column(name = "uid")
2328
@GeneratedValue(generator = "UUID")
@@ -27,8 +32,6 @@ public class Member extends BaseEntity implements Serializable {
2732

2833
private String password;
2934

30-
private String salt;
31-
3235
private Integer state;
3336

3437
private String createdAt;
@@ -67,14 +70,6 @@ public void setPassword(String password) {
6770
this.password = password;
6871
}
6972

70-
public String getSalt() {
71-
return salt;
72-
}
73-
74-
public void setSalt(String salt) {
75-
this.salt = salt;
76-
}
77-
7873
public Integer getState() {
7974
return state;
8075
}
@@ -114,4 +109,36 @@ public String getOrder() {
114109
public void setOrder(String order) {
115110
this.order = order;
116111
}
112+
113+
@Override
114+
public Collection<? extends GrantedAuthority> getAuthorities() {
115+
List<GrantedAuthority> auths = new ArrayList<>();
116+
return auths;
117+
}
118+
119+
@Override
120+
public String getUsername() {
121+
return this.account;
122+
}
123+
124+
@Override
125+
public boolean isAccountNonExpired() {
126+
return false;
127+
}
128+
129+
@Override
130+
public boolean isAccountNonLocked() {
131+
return false;
132+
}
133+
134+
@Override
135+
public boolean isCredentialsNonExpired() {
136+
return false;
137+
}
138+
139+
@Override
140+
public boolean isEnabled() {
141+
return false;
142+
}
143+
117144
}

‎src/main/java/com/geekcattle/util/JsonUtil.java

+26-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package com.geekcattle.util;
66

77
import com.alibaba.fastjson.JSON;
8+
import org.apache.commons.lang3.StringUtils;
89

910
import java.util.HashMap;
1011
import java.util.Map;
@@ -21,15 +22,39 @@ public static Object parse(String json) {
2122
return JSON.parse(json);
2223
}
2324

25+
public static String toJsonSuccess(){
26+
return toJsonSuccess("成功");
27+
}
28+
29+
public static String toJsonSuccess(String msg){
30+
return toJsonSuccess(msg, new Object());
31+
}
32+
33+
public static String toJsonSuccess(Object obj){
34+
return toJsonSuccess("成功", obj);
35+
}
36+
2437
public static String toJsonSuccess(String msg, Object obj){
2538
Map<String,Object> mp = new HashMap<String, Object>();
2639
mp.put("status", 1);
2740
mp.put("state", "success");
28-
mp.put("msg", msg);
41+
mp.put("msg", msg.getBytes());
2942
mp.put("result", obj);
3043
return toJson(mp);
3144
}
3245

46+
public static String toJsonError(){
47+
return toJsonError("失败");
48+
}
49+
50+
public static String toJsonError(String msg){
51+
return toJsonError(msg, new Object());
52+
}
53+
54+
public static String toJsonError(Object obj){
55+
return toJsonError("失败", obj);
56+
}
57+
3358
public static String toJsonError(String msg, Object obj){
3459
Map<String,Object> mp = new HashMap<String, Object>();
3560
mp.put("status", 0);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package com.geekcattle.util;
2+
3+
import java.security.MessageDigest;
4+
5+
/**
6+
* MD5加密工具
7+
*
8+
*/
9+
public class MD5Util {
10+
11+
/**
12+
* 密码加密
13+
* @param password
14+
* @return
15+
*/
16+
public static String encode(String password) {
17+
return processEncode(password);
18+
}
19+
20+
public static String processEncode(String password) {
21+
MessageDigest md5 = null;
22+
try {
23+
md5 = MessageDigest.getInstance("MD5");
24+
} catch (Exception e) {
25+
throw new RuntimeException(e);
26+
}
27+
char[] charArray = password.toCharArray();
28+
byte[] byteArray = new byte[charArray.length];
29+
30+
for (int i = 0; i < charArray.length; i++)
31+
byteArray[i] = (byte) charArray[i];
32+
byte[] md5Bytes = md5.digest(byteArray);
33+
StringBuffer hexValue = new StringBuffer();
34+
for (int i = 0; i < md5Bytes.length; i++) {
35+
int val = ((int) md5Bytes[i]) & 0xff;
36+
if (val < 16) {
37+
hexValue.append("0");
38+
}
39+
40+
hexValue.append(Integer.toHexString(val));
41+
}
42+
return hexValue.toString();
43+
}
44+
45+
}

‎src/main/resources/application.properties

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# 项目contextPath,一般在正式发布版本中,我们不配置
22
server.servlet.context-path = /
33
# session最大超时时间(分钟),默认为30
4-
server.session-timeout = 60
4+
server.servlet.session.timeout = 60M
5+
server.servlet.session.tracking-modes = cookie
56
#日志配置
67
logging.level.com.geekcattle.mapper = DEBUG
78
logging.file=logs/spring-boot-logging.log
@@ -17,9 +18,6 @@ j2cache.config-location=/j2cache.properties
1718
j2cache.open-spring-cache=true
1819
spring.cache.type = none
1920

20-
21-
22-
2321
# 使用druid数据源
2422
spring.datasource.type = com.alibaba.druid.pool.DruidDataSource
2523
spring.datasource.driver-class-name = com.mysql.jdbc.Driver

‎src/main/resources/templates/member/login.html

+24-8
Original file line numberDiff line numberDiff line change
@@ -6,23 +6,36 @@
66
<body>
77
<div class="container-fluid">
88
<div class="row">
9-
<div class="col-md-4 col-md-offset-4">
9+
<div class="col-md-4 col-md-offset-1">
1010
<form class="ajaxforms" method="post" action="/member/login">
1111
<div class="form-group">
12-
<label for="account">账号</label>
13-
<input type="text" class="form-control" name="account" id="account" placeholder="账号">
12+
<label>账号</label>
13+
<input type="text" class="form-control" name="account" placeholder="账号">
1414
</div>
1515
<div class="form-group">
16-
<label for="password">密码</label>
17-
<input type="password" name="password" class="form-control" id="password" placeholder="密码">
16+
<label>密码</label>
17+
<input type="password" class="form-control" name="password" placeholder="密码">
1818
</div>
19-
<input type="submit" class="form-control btn-primary" value="登录" />
19+
<input type="submit" class="form-control btn-primary" value="AJAX登录" />
20+
</form>
21+
</div>
22+
<div class="col-md-4 col-md-offset-1">
23+
<form method="post" action="/member/login">
24+
<div class="form-group">
25+
<label>账号</label>
26+
<input type="text" class="form-control" name="account" placeholder="账号">
27+
</div>
28+
<div class="form-group">
29+
<label>密码</label>
30+
<input type="password" class="form-control" name="password" placeholder="密码">
31+
</div>
32+
<input type="submit" class="form-control btn-primary" value="默认登录" />
2033
</form>
2134
</div>
2235
</div>
2336
</div>
2437

25-
<div th:include="member/footer"></div>
38+
<div th:replace="member/footer"></div>
2639

2740
<script type="text/javascript">
2841
$(function () {
@@ -51,7 +64,7 @@
5164
},
5265
'password' : {
5366
required : '请输入密码'
54-
},
67+
}
5568
},
5669
submitHandler : function(forms) {
5770
if (formloading) return;
@@ -68,6 +81,9 @@
6881
} else {
6982
layer.msg(data.msg);
7083
}
84+
},
85+
error : function () {
86+
7187
}
7288
});
7389
}

‎src/test/java/TestApp.java

+21-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
import com.geekcattle.Application;
2+
import com.geekcattle.mapper.member.MemberMapper;
3+
import com.geekcattle.model.member.Member;
4+
import com.geekcattle.service.member.MemberService;
25
import junit.framework.TestCase;
36
import net.oschina.j2cache.CacheChannel;
47
import net.oschina.j2cache.J2Cache;
@@ -9,9 +12,12 @@
912
import org.springframework.beans.factory.annotation.Autowired;
1013
import org.springframework.boot.test.context.SpringBootTest;
1114
import org.springframework.data.redis.core.RedisTemplate;
15+
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
1216
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
1317
import redis.clients.jedis.JedisPool;
1418

19+
import java.util.List;
20+
1521
/**
1622
* author geekcattle
1723
* date 2016/10/21 0021 下午 16:54
@@ -28,6 +34,9 @@ public class TestApp extends TestCase {
2834
@Autowired
2935
RedisTemplate<String, String> redisTemplate;
3036

37+
@Autowired
38+
MemberMapper memberMapper;
39+
3140
@Test
3241
public void testRedis(){
3342
redisTemplate.boundValueOps("geekcattle").set("df1111111111111");
@@ -45,16 +54,25 @@ public static void main(String[] args) {
4554
@Test
4655
public void testJ2Cache(){
4756
CacheChannel cache = J2Cache.getChannel();
48-
4957
//缓存操作
5058
System.out.println(cache.get("default", "1"));
5159
cache.set("default", "1", "Hello J2Cache");
5260
System.out.println(cache.get("default", "1"));
5361
cache.evict("default", "1");
54-
55-
5662
cache.close();
5763
}
5864

65+
@Test
66+
public void modifyPassword(){
67+
List<Member> lists = memberMapper.selectAll();
68+
for (Member member : lists) {
69+
BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
70+
String newPassword = passwordEncoder.encode("hao123");
71+
System.out.printf(newPassword);
72+
member.setPassword(newPassword);
73+
memberMapper.updateByPrimaryKey(member);
74+
}
75+
}
76+
5977

6078
}

‎startup.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/bin/sh
22
rm -f tpid
3-
nohup java -jar target/spring-boot-admin.jar --spring.profiles.active=pro > /var/log/spring-boot-web/startup`date +%Y-%m-%d`.log 2>&1 &
3+
nohup java -jar target/geek-framework.jar --spring.profiles.active=pro > /var/log/spring-boot-web/startup`date +%Y-%m-%d`.log 2>&1 &
44
echo $! > tpid
55
echo Start Success!

0 commit comments

Comments
 (0)
Please sign in to comment.