filters = new LinkedHashMap<>();
61 | filters.put("jwt", new JwtFilter());
62 | shiroFilterFactoryBean.setFilters(filters);
63 |
64 | // 所有请求都要经过 jwt过滤器
65 | filterChainDefinitionMap.put("/**", "jwt");
66 |
67 | shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
68 | logger.warn("Shiro jwt 拦截器工厂类注入成功");
69 | return shiroFilterFactoryBean;
70 | }
71 |
72 | @Bean
73 | public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
74 | AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
75 | authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
76 | return authorizationAttributeSourceAdvisor;
77 | }
78 |
79 | /**
80 | * 注入 securityManager
81 | */
82 | @Bean
83 | public SecurityManager securityManager() {
84 | DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
85 | // 设置realm.
86 | securityManager.setRealm(customRealm());
87 |
88 | // 设置缓存
89 | securityManager.setCacheManager(cacheManager());
90 |
91 | // 设置会话
92 | securityManager.setSessionManager(sessionManager());
93 | return securityManager;
94 | }
95 |
96 | /**
97 | * 自定义身份认证 realm;
98 | *
99 | * 必须写这个类,并加上 @Bean 注解,目的是注入 CustomRealm,
100 | * 否则会影响 CustomRealm类 中其他类的依赖注入
101 | */
102 | @Bean
103 | public CustomRealm customRealm() {
104 | return new CustomRealm();
105 | }
106 |
107 |
108 | /**
109 | * 加入redis缓存,避免重复从数据库获取数据
110 | */
111 | public RedisManager redisManager() {
112 | RedisManager redisManager = new RedisManager();
113 | redisManager.setHost(redisHost);
114 | redisManager.setPort(redisPort);
115 | redisManager.setPassword(redisPassword);
116 | redisManager.setExpire(expireAt);
117 | redisManager.setTimeout(timeout);
118 | return redisManager;
119 | }
120 |
121 | public RedisCacheManager cacheManager() {
122 | RedisCacheManager redisCacheManager = new RedisCacheManager();
123 | redisCacheManager.setRedisManager(redisManager());
124 | return redisCacheManager;
125 | }
126 |
127 |
128 | /**
129 | * session 会话管理
130 | */
131 | @Bean
132 | public RedisSessionDAO sessionDAO() {
133 | RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
134 | redisSessionDAO.setRedisManager(redisManager());
135 | return redisSessionDAO;
136 | }
137 |
138 | @Bean
139 | public SimpleCookie sessionIdCookie(){
140 | SimpleCookie cookie = new SimpleCookie("X-Token");
141 | cookie.setMaxAge(-1);
142 | cookie.setPath("/");
143 | cookie.setHttpOnly(false);
144 | return cookie;
145 | }
146 |
147 | @Bean
148 | public SessionManager sessionManager() {
149 | DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
150 | sessionManager.setSessionIdCookie(sessionIdCookie());
151 | sessionManager.setSessionIdCookieEnabled(true);
152 | Collection listeners = new ArrayList();
153 | listeners.add(new ShiroSessionListener());
154 | sessionManager.setSessionListeners(listeners);
155 | sessionManager.setSessionDAO(sessionDAO());
156 | return sessionManager;
157 | }
158 | }
159 |
160 |
--------------------------------------------------------------------------------
/springboot-shiro/src/main/java/com/example/shiro/config/CustomRealm.java:
--------------------------------------------------------------------------------
1 | package com.example.shiro.config;
2 |
3 | import com.example.shiro.dao.User;
4 | import com.example.shiro.mock.UserMock;
5 | import org.apache.shiro.SecurityUtils;
6 | import org.apache.shiro.authc.*;
7 | import org.apache.shiro.authz.AuthorizationInfo;
8 | import org.apache.shiro.authz.SimpleAuthorizationInfo;
9 | import org.apache.shiro.realm.AuthorizingRealm;
10 | import org.apache.shiro.subject.PrincipalCollection;
11 |
12 | import java.util.HashSet;
13 | import java.util.Set;
14 |
15 | /**
16 | * @author qcl
17 | * @version 1.0
18 | * @date 2022/4/26 10:56 AM
19 | * @description
20 | */
21 | public class CustomRealm extends AuthorizingRealm {
22 |
23 | /**
24 | * 登录认证
25 | */
26 | @Override
27 | protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
28 |
29 | // 获取用户输入的用户名和密码
30 | String userName = (String) token.getPrincipal();
31 | String password = new String((char[]) token.getCredentials());
32 |
33 | System.out.println("用户" + userName + "认证-----ShiroRealm.doGetAuthenticationInfo");
34 |
35 | // 通过用户名到数据库查询用户信息
36 | User user = UserMock.getUserByUsername(userName);
37 |
38 | if (user == null) {
39 | throw new UnknownAccountException("用户名或密码错误!");
40 | }
41 | if (!password.equals(user.getPassword())) {
42 | throw new IncorrectCredentialsException("用户名或密码错误!");
43 | }
44 | if (user.getState().equals("0")) {
45 | throw new LockedAccountException("账号已被锁定,请联系管理员!");
46 | }
47 | SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());
48 | return info;
49 | }
50 |
51 |
52 | /**
53 | * 获取用户角色和权限
54 | */
55 | @Override
56 | protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
57 | User user = (User) SecurityUtils.getSubject().getPrincipal();
58 | String userName = user.getUsername();
59 | SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
60 |
61 | // 获取用户角色
62 | Set roleSet = new HashSet<>();
63 | String role = UserMock.getRole(userName);
64 | roleSet.add(role);
65 | simpleAuthorizationInfo.setRoles(roleSet);
66 |
67 | // 获取用户权限
68 | String permission = UserMock.getPermission(userName);
69 | Set permissionSet = new HashSet();
70 | permissionSet.add(permission);
71 | simpleAuthorizationInfo.setStringPermissions(permissionSet);
72 | return simpleAuthorizationInfo;
73 | }
74 |
75 | }
76 |
--------------------------------------------------------------------------------
/springboot-shiro/src/main/java/com/example/shiro/config/ShiroConfig.java:
--------------------------------------------------------------------------------
1 | package com.example.shiro.config;
2 |
3 | import cn.hutool.core.codec.Base64;
4 | import org.apache.shiro.mgt.SecurityManager;
5 | import org.apache.shiro.session.SessionListener;
6 | import org.apache.shiro.session.mgt.SessionManager;
7 | import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
8 | import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
9 | import org.apache.shiro.web.mgt.CookieRememberMeManager;
10 | import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
11 | import org.apache.shiro.web.servlet.SimpleCookie;
12 | import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
13 | import org.crazycake.shiro.RedisCacheManager;
14 | import org.crazycake.shiro.RedisManager;
15 | import org.crazycake.shiro.RedisSessionDAO;
16 | import org.springframework.context.annotation.Bean;
17 | import org.springframework.context.annotation.Configuration;
18 |
19 | import java.util.ArrayList;
20 | import java.util.Collection;
21 | import java.util.LinkedHashMap;
22 |
23 | /**
24 | * @author qcl
25 | * @version 1.0
26 | * @date 2022/4/26 10:55 AM
27 | * @description
28 | */
29 | @Configuration
30 | public class ShiroConfig {
31 | @Bean
32 | public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
33 | ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
34 | // 设置securityManager
35 | shiroFilterFactoryBean.setSecurityManager((SecurityManager) securityManager);
36 | // 登录的url
37 | shiroFilterFactoryBean.setLoginUrl("/login");
38 | // 登录成功后跳转的url
39 | shiroFilterFactoryBean.setSuccessUrl("/index");
40 | // 未授权url
41 | shiroFilterFactoryBean.setUnauthorizedUrl("/403");
42 |
43 | LinkedHashMap filterChainDefinitionMap = new LinkedHashMap<>();
44 |
45 | // 定义filterChain,静态资源不拦截
46 | filterChainDefinitionMap.put("/css/**", "anon");
47 | filterChainDefinitionMap.put("/js/**", "anon");
48 | filterChainDefinitionMap.put("/fonts/**", "anon");
49 | filterChainDefinitionMap.put("/img/**", "anon");
50 | // druid数据源监控页面不拦截
51 | filterChainDefinitionMap.put("/druid/**", "anon");
52 | // 配置退出过滤器,其中具体的退出代码Shiro已经替我们实现了
53 | filterChainDefinitionMap.put("/logout", "logout");
54 | filterChainDefinitionMap.put("/", "anon");
55 | // 除上以外所有url都必须认证通过才可以访问,未通过认证自动访问LoginUrl
56 | // filterChainDefinitionMap.put("/**", "authc");
57 | filterChainDefinitionMap.put("/**", "user");
58 |
59 | shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
60 | return shiroFilterFactoryBean;
61 | }
62 |
63 | @Bean
64 | public SecurityManager securityManager(){
65 | DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
66 | securityManager.setRealm(shiroRealm());
67 | securityManager.setRememberMeManager(rememberMeManager());
68 | securityManager.setCacheManager(cacheManager());
69 | securityManager.setSessionManager(sessionManager());
70 | return securityManager;
71 | }
72 |
73 | /**
74 | * 自定义实现的Realm
75 | * @return
76 | */
77 | @Bean
78 | public CustomRealm shiroRealm(){
79 | CustomRealm shiroRealm = new CustomRealm();
80 | return shiroRealm;
81 | }
82 |
83 | /**
84 | * cookie
85 | * @return
86 | */
87 | public SimpleCookie rememberMeCookie() {
88 | // 设置cookie名称
89 | SimpleCookie cookie = new SimpleCookie("rememberMe");
90 | // 单位为秒
91 | cookie.setMaxAge(86400);
92 | return cookie;
93 | }
94 |
95 | /**
96 | * cookie管理对象
97 | * @return
98 | */
99 | public CookieRememberMeManager rememberMeManager() {
100 | CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
101 | cookieRememberMeManager.setCookie(rememberMeCookie());
102 | // cookie加密的密钥
103 | cookieRememberMeManager.setCipherKey(Base64.decode("uwandaljILlia458ad4"));
104 | return cookieRememberMeManager;
105 | }
106 |
107 | /**
108 | * 开启注解
109 | * @param securityManager
110 | * @return
111 | */
112 | @Bean
113 | public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
114 | AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
115 | authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
116 | return authorizationAttributeSourceAdvisor;
117 | }
118 |
119 | public RedisManager redisManager() {
120 | RedisManager redisManager = new RedisManager();
121 | return redisManager;
122 | }
123 |
124 | public RedisCacheManager cacheManager() {
125 | RedisCacheManager redisCacheManager = new RedisCacheManager();
126 | redisCacheManager.setRedisManager(redisManager());
127 | return redisCacheManager;
128 | }
129 |
130 | @Bean
131 | public RedisSessionDAO sessionDAO() {
132 | RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
133 | redisSessionDAO.setRedisManager(redisManager());
134 | return redisSessionDAO;
135 | }
136 |
137 | @Bean
138 | public SessionManager sessionManager() {
139 | DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
140 | Collection listeners = new ArrayList();
141 | listeners.add(new ShiroSessionListener());
142 | sessionManager.setSessionListeners(listeners);
143 | sessionManager.setSessionDAO(sessionDAO());
144 | return sessionManager;
145 | }
146 |
147 | }
148 |
--------------------------------------------------------------------------------
/springboot-shiro/src/main/java/com/example/shiro/config/ShiroSessionListener.java:
--------------------------------------------------------------------------------
1 | package com.example.shiro.config;
2 |
3 | import org.apache.shiro.session.Session;
4 | import org.apache.shiro.session.SessionListener;
5 |
6 | import java.util.concurrent.atomic.AtomicInteger;
7 |
8 | /**
9 | * @author qcl
10 | * @version 1.0
11 | * @date 2022/4/29 10:24 AM
12 | * @description
13 | */
14 | public class ShiroSessionListener implements SessionListener {
15 | private final AtomicInteger sessionCount = new AtomicInteger(0);
16 |
17 | @Override
18 | public void onStart(Session session) {
19 | sessionCount.incrementAndGet();
20 | }
21 |
22 | @Override
23 | public void onStop(Session session) {
24 | sessionCount.decrementAndGet();
25 | }
26 |
27 | @Override
28 | public void onExpiration(Session session) {
29 | sessionCount.decrementAndGet();
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/springboot-shiro/src/main/java/com/example/shiro/controller/ExceptionController.java:
--------------------------------------------------------------------------------
1 | package com.example.shiro.controller;
2 |
3 | import org.apache.shiro.authz.AuthorizationException;
4 | import org.springframework.web.bind.annotation.ControllerAdvice;
5 | import org.springframework.web.bind.annotation.ExceptionHandler;
6 |
7 | /**
8 | * @author qcl
9 | * @version 1.0
10 | * @date 2022/4/28 10:54 AM
11 | * @description
12 | */
13 | @ControllerAdvice
14 | public class ExceptionController {
15 | @ExceptionHandler(value = AuthorizationException.class)
16 | public String handleAuthorizationException() {
17 | return "您当前没有权限访问~ 请联系管理员";
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/springboot-shiro/src/main/java/com/example/shiro/controller/IndexController.java:
--------------------------------------------------------------------------------
1 | package com.example.shiro.controller;
2 |
3 | import com.example.shiro.dao.User;
4 | import com.example.shiro.dao.UserOnline;
5 | import org.apache.shiro.SecurityUtils;
6 | import org.apache.shiro.authz.annotation.RequiresPermissions;
7 | import org.apache.shiro.session.Session;
8 | import org.apache.shiro.session.mgt.eis.SessionDAO;
9 | import org.apache.shiro.subject.SimplePrincipalCollection;
10 | import org.apache.shiro.subject.support.DefaultSubjectContext;
11 | import org.springframework.beans.factory.annotation.Autowired;
12 | import org.springframework.ui.Model;
13 | import org.springframework.web.bind.annotation.RequestMapping;
14 | import org.springframework.web.bind.annotation.ResponseBody;
15 | import org.springframework.web.bind.annotation.RestController;
16 |
17 | import java.util.ArrayList;
18 | import java.util.Collection;
19 | import java.util.List;
20 |
21 | /**
22 | * @author qcl
23 | * @version 1.0
24 | * @date 2022/4/26 11:22 AM
25 | * @description
26 | */
27 | @RestController
28 | public class IndexController {
29 |
30 | @Autowired
31 | private SessionDAO sessionDAO;
32 |
33 | @RequiresPermissions("p:user")
34 | @RequestMapping("/index")
35 | public String index(Model model) {
36 | // 登录成后,即可通过Subject获取登录的用户信息
37 | User user = (User) SecurityUtils.getSubject().getPrincipal();
38 | model.addAttribute("user", user);
39 | return "index --->" + user.getUsername();
40 | }
41 |
42 | @RequiresPermissions("p:admin")
43 | @RequestMapping("/userOnline/list")
44 | @ResponseBody
45 | public List list() {
46 | List list = new ArrayList<>();
47 | Collection sessions = sessionDAO.getActiveSessions();
48 | for (Session session : sessions) {
49 | UserOnline userOnline = new UserOnline();
50 | User user = new User();
51 | SimplePrincipalCollection principalCollection;
52 | if (session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY) == null) {
53 | continue;
54 | } else {
55 | principalCollection = (SimplePrincipalCollection) session
56 | .getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
57 | user = (User) principalCollection.getPrimaryPrincipal();
58 | userOnline.setUsername(user.getUsername());
59 | userOnline.setUserId(user.getId().toString());
60 | }
61 | userOnline.setSessionId((String) session.getId());
62 | userOnline.setHost(session.getHost());
63 | userOnline.setStartTime(session.getStartTimestamp());
64 | userOnline.setLastTime(session.getLastAccessTime());
65 | Long timeout = session.getTimeout();
66 | if (timeout == 0l) {
67 | userOnline.setStatus("离线");
68 | } else {
69 | userOnline.setStatus("在线");
70 | }
71 | userOnline.setTimeout(timeout);
72 | list.add(userOnline);
73 | }
74 | return list;
75 | }
76 |
77 | @RequiresPermissions("p:admin")
78 | @RequestMapping("/forceLogout")
79 | @ResponseBody
80 | public boolean forceLogout(String sessionId) {
81 | Session session = sessionDAO.readSession(sessionId);
82 | session.setTimeout(0);
83 | return true;
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/springboot-shiro/src/main/java/com/example/shiro/controller/LoginController.java:
--------------------------------------------------------------------------------
1 | package com.example.shiro.controller;
2 |
3 | import com.example.shiro.dao.User;
4 | import org.apache.shiro.SecurityUtils;
5 | import org.apache.shiro.authc.*;
6 | import org.apache.shiro.subject.Subject;
7 | import org.springframework.ui.Model;
8 | import org.springframework.web.bind.annotation.*;
9 |
10 | /**
11 | * @author qcl
12 | * @version 1.0
13 | * @date 2022/4/26 10:53 AM
14 | * @description
15 | */
16 | @RestController
17 | public class LoginController {
18 | @GetMapping("/login")
19 | public String login() {
20 | return "login";
21 | }
22 |
23 | @PostMapping("/login")
24 | @ResponseBody
25 | public String login(String username, String password) {
26 | //UsernamePasswordToken token = new UsernamePasswordToken(username, password);
27 | // 获取Subject对象
28 | UsernamePasswordToken token = new UsernamePasswordToken(username, password, true);
29 | Subject subject = SecurityUtils.getSubject();
30 | try {
31 | // 执行登录
32 | subject.login(token);
33 | return "ok";
34 | } catch (UnknownAccountException e) {
35 | return e.getMessage();
36 | } catch (IncorrectCredentialsException e) {
37 | return "IncorrectCredentialsException " + e.getMessage();
38 | } catch (LockedAccountException e) {
39 | return "LockedAccountException " + e.getMessage();
40 | } catch (AuthenticationException e) {
41 | return "认证失败!";
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/springboot-shiro/src/main/java/com/example/shiro/dao/User.java:
--------------------------------------------------------------------------------
1 | package com.example.shiro.dao;
2 |
3 | import lombok.Data;
4 |
5 | /**
6 | * @author qcl
7 | * @version 1.0
8 | * @date 2022/4/26 11:13 AM
9 | * @description
10 | */
11 | @Data
12 | public class User {
13 | public Integer id;
14 | public String userId;
15 | public String username;
16 | public String password;
17 | public String role;
18 | public String state;
19 | public String permission;
20 | }
21 |
--------------------------------------------------------------------------------
/springboot-shiro/src/main/java/com/example/shiro/dao/UserOnline.java:
--------------------------------------------------------------------------------
1 | package com.example.shiro.dao;
2 |
3 | import lombok.Data;
4 |
5 | import java.io.Serializable;
6 | import java.util.Date;
7 |
8 | /**
9 | * @author qcl
10 | * @version 1.0
11 | * @date 2022/4/29 10:30 AM
12 | * @description
13 | */
14 | @Data
15 | public class UserOnline implements Serializable {
16 |
17 | private static final long serialVersionUID = 3828664348416633856L;
18 |
19 | private String sessionId;
20 |
21 | private String userId;
22 |
23 | private String username;
24 |
25 | private String host;
26 |
27 | private String ip;
28 |
29 | private String status;
30 |
31 | private Date startTime;
32 |
33 | private Date lastTime;
34 |
35 | private Long timeout;
36 | }
37 |
--------------------------------------------------------------------------------
/springboot-shiro/src/main/java/com/example/shiro/mock/UserMock.java:
--------------------------------------------------------------------------------
1 | package com.example.shiro.mock;
2 |
3 | import com.example.shiro.dao.User;
4 |
5 | /**
6 | * @author qcl
7 | * @version 1.0
8 | * @date 2022/4/26 11:14 AM
9 | * @description 用户数据模拟
10 | */
11 | public class UserMock {
12 |
13 | public static String getPassword(String username) {
14 | System.out.println("用户名: " + username);
15 | if(username.equals("admin")) {
16 | return "123";
17 | }else {
18 | return "456";
19 | }
20 | }
21 |
22 | public static String getRole(String username) {
23 | if(username.equals("admin")) {
24 | return "admin";
25 | }else {
26 | return "user";
27 | }
28 | }
29 |
30 | public static String getRoleById(String userId) {
31 | if(userId.equals("1")) {
32 | return "admin";
33 | }else {
34 | return "user";
35 | }
36 | }
37 |
38 | public static String getPermission(String username) {
39 | if(username.equals("admin")) {
40 | return "p:admin";
41 | }else {
42 | return "P:user";
43 | }
44 | }
45 |
46 | public static User getUserByUsername(String username) {
47 | User user = new User();
48 | if(username.equals("admin")) {
49 | user.setUsername("admin");
50 | user.setPassword("123");
51 | user.setRole("admin");
52 | }else {
53 | user.setUsername("admin1");
54 | user.setPassword("456");
55 | user.setRole("user");
56 | }
57 | user.setState("1");
58 | return user;
59 | }
60 |
61 | }
62 |
63 |
--------------------------------------------------------------------------------
/springboot-shiro/src/main/resources/application-dev.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8878 # 设置应用端口,默认是8080
3 | tomcat:
4 | max-threads: 800
5 | uri-encoding: UTF-8
6 | servlet:
7 | context-path: /dev-api
8 |
9 | spring:
10 | application:
11 | name: app-shiro
12 | datasource:
13 | url: jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true
14 | username: root
15 | password: qcl123456
16 | redis:
17 | host: localhost # Redis服务器地址
18 | database: 1 # Redis数据库索引(默认为0)
19 | port: 6379 # Redis服务器连接端口
20 | password: # Redis服务器连接密码(默认为空)
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/springboot-shiro/src/main/resources/application-prod.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8888 # 设置应用端口,默认是8080
3 | tomcat:
4 | max-threads: 800
5 | uri-encoding: UTF-8
6 | servlet:
7 | context-path: /prod-api
8 |
9 | spring:
10 | application:
11 | name: app-shiro
12 | datasource:
13 | url: jdbc:mysql://xxx.xxx.xxx.xxx:3306/test?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true
14 | username: xxx
15 | password: xxxxxxx
16 | redis:
17 | host: xxxxx # Redis服务器地址
18 | database: x # Redis数据库索引(默认为0)
19 | port: 6379 # Redis服务器连接端口
20 | password: xxxx # Redis服务器连接密码(默认为空)
--------------------------------------------------------------------------------
/springboot-shiro/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 |
2 | spring:
3 | profiles:
4 | active: @profile.active@
5 |
6 | mybatis:
7 | mapper-locations:
8 | - classpath:mapper/*.xml
9 | configuration:
10 | cache-enabled: true
11 | log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/springboot-shiro/src/main/resources/logback-spring.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | ${APP_NAME}
11 |
12 |
13 |
14 | ${LOG_FILE_PATH}/${APP_NAME}-%d{yyyy-MM-dd}.log
15 | 30
16 |
17 |
18 | ${FILE_LOG_PATTERN}
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/springboot-study/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | springboot-all
7 | org.example
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | springboot-study
13 |
14 |
15 | 8
16 | 8
17 |
18 |
19 |
--------------------------------------------------------------------------------
/springboot-study/src/main/java/com/example/app/Application.java:
--------------------------------------------------------------------------------
1 | package com.example.app;
2 |
3 | import com.example.app.config.AppConfig;
4 | import org.springframework.boot.Banner;
5 | import org.springframework.boot.SpringApplication;
6 | import org.springframework.boot.autoconfigure.SpringBootApplication;
7 | import org.springframework.boot.context.properties.EnableConfigurationProperties;
8 | import org.springframework.transaction.annotation.EnableTransactionManagement;
9 |
10 | /**
11 | * @author qcl
12 | * @version 1.0
13 | * @date 2022/4/8 9:45 AM
14 | * @description
15 | */
16 | @EnableTransactionManagement
17 | @EnableConfigurationProperties({AppConfig.class})
18 | @SpringBootApplication
19 | public class Application {
20 | public static void main(String[] args) {
21 | SpringApplication app = new SpringApplication(Application.class);
22 | // 关闭 banner
23 | app.setBannerMode(Banner.Mode.OFF);
24 | app.run(args);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/springboot-study/src/main/java/com/example/app/common/CommonPage.java:
--------------------------------------------------------------------------------
1 | package com.example.app.common;
2 |
3 | import com.github.pagehelper.PageHelper;
4 | import com.github.pagehelper.PageInfo;
5 |
6 | import java.util.List;
7 |
8 | /**
9 | * @author qcl
10 | * @version 1.0
11 | * @date 2022/4/18 11:08 AM
12 | * @description
13 | */
14 | public class CommonPage {
15 | private Integer pageNum;
16 | private Integer pageSize;
17 | private Long total;
18 | private List list;
19 |
20 | /**
21 | * 将PageHelper分页后的list转为分页信息
22 | */
23 | public static CommonPage restPage(List list) {
24 | CommonPage result = new CommonPage();
25 | PageInfo pageInfo = new PageInfo(list);
26 | result.setPageNum(pageInfo.getPageNum());
27 | result.setPageSize(pageInfo.getPageSize());
28 | result.setTotal(pageInfo.getTotal());
29 | result.setList(pageInfo.getList());
30 | return result;
31 | }
32 |
33 | public static void setPageHelper(Integer pageNum, Integer pageSize) {
34 | if(pageNum == null || pageNum <= 0) {
35 | pageNum = 1;
36 | }
37 |
38 | if(pageSize == null || pageSize <= 0) {
39 | pageSize = 10;
40 | }
41 |
42 | if(pageSize >= 20) {
43 | pageSize = 20;
44 | }
45 |
46 | PageHelper.startPage(pageNum, pageSize);
47 | }
48 |
49 | public Integer getPageNum() {
50 | return pageNum;
51 | }
52 |
53 | public void setPageNum(Integer pageNum) {
54 | this.pageNum = pageNum;
55 | }
56 |
57 | public Integer getPageSize() {
58 | return pageSize;
59 | }
60 |
61 | public void setPageSize(Integer pageSize) {
62 | this.pageSize = pageSize;
63 | }
64 |
65 | public List getList() {
66 | return list;
67 | }
68 |
69 | public void setList(List list) {
70 | this.list = list;
71 | }
72 |
73 | public Long getTotal() {
74 | return total;
75 | }
76 |
77 | public void setTotal(Long total) {
78 | this.total = total;
79 | }
80 | }
81 |
82 |
83 |
--------------------------------------------------------------------------------
/springboot-study/src/main/java/com/example/app/component/App.java:
--------------------------------------------------------------------------------
1 | package com.example.app.component;
2 |
3 | import org.springframework.beans.factory.annotation.Value;
4 | import org.springframework.stereotype.Component;
5 |
6 | /**
7 | * @author qcl
8 | * @version 1.0
9 | * @date 2022/4/8 10:59 AM
10 | * @description
11 | */
12 | @Component
13 | public class App {
14 |
15 | @Value("${app.name}")
16 | private String name;
17 |
18 | @Value("${app.version}")
19 | private String version;
20 |
21 | public String getName() {
22 | return name;
23 | }
24 |
25 |
26 | public String getVersion() {
27 | return version;
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/springboot-study/src/main/java/com/example/app/component/RedisUtil.java:
--------------------------------------------------------------------------------
1 | package com.example.app.component;
2 |
3 | import org.springframework.beans.factory.annotation.Autowired;
4 | import org.springframework.data.redis.core.StringRedisTemplate;
5 | import org.springframework.stereotype.Component;
6 |
7 | import java.util.concurrent.TimeUnit;
8 |
9 | /**
10 | * @author qcl
11 | * @version 1.0
12 | * @date 2022/4/15 10:37 AM
13 | * @description
14 | */
15 | @Component
16 | public class RedisUtil {
17 |
18 | @Autowired
19 | private StringRedisTemplate stringRedisTemplate;
20 |
21 | public void set(String key, String value) {
22 | stringRedisTemplate.opsForValue().set(key, value);
23 | }
24 |
25 | public String get(String key) {
26 | return stringRedisTemplate.opsForValue().get(key);
27 | }
28 |
29 | public boolean expire(String key, long expire) {
30 | return stringRedisTemplate.expire(key, expire, TimeUnit.SECONDS);
31 | }
32 |
33 | public void remove(String key) {
34 | stringRedisTemplate.delete(key);
35 | }
36 |
37 | public Long increment(String key, long delta) {
38 | return stringRedisTemplate.opsForValue().increment(key,delta);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/springboot-study/src/main/java/com/example/app/component/WebLogFilter.java:
--------------------------------------------------------------------------------
1 | package com.example.app.component;
2 |
3 | import cn.hutool.core.util.StrUtil;
4 | import cn.hutool.json.JSONUtil;
5 | import com.example.app.dto.WebLog;
6 | import org.aspectj.lang.JoinPoint;
7 | import org.aspectj.lang.ProceedingJoinPoint;
8 | import org.aspectj.lang.Signature;
9 | import org.aspectj.lang.annotation.*;
10 | import org.aspectj.lang.reflect.MethodSignature;
11 | import org.slf4j.Logger;
12 | import org.slf4j.LoggerFactory;
13 | import org.springframework.core.annotation.Order;
14 | import org.springframework.stereotype.Component;
15 | import org.springframework.util.StringUtils;
16 | import org.springframework.web.bind.annotation.RequestBody;
17 | import org.springframework.web.bind.annotation.RequestParam;
18 | import org.springframework.web.context.request.RequestContextHolder;
19 | import org.springframework.web.context.request.ServletRequestAttributes;
20 | import cn.hutool.core.util.URLUtil;
21 |
22 | import javax.servlet.http.HttpServletRequest;
23 | import java.lang.reflect.Method;
24 | import java.lang.reflect.Parameter;
25 | import java.util.ArrayList;
26 | import java.util.HashMap;
27 | import java.util.List;
28 | import java.util.Map;
29 |
30 | /**
31 | * @author qcl
32 | * @version 1.0
33 | * @date 2022/4/21 10:36 AM
34 | * @description
35 | */
36 | @Aspect
37 | @Component
38 | @Order(1)
39 | public class WebLogFilter {
40 | private static final Logger LOGGER = LoggerFactory.getLogger(WebLogFilter.class);
41 |
42 | @Pointcut("execution(public * com.example.app.controller.*.*(..))")
43 | public void webLog() {
44 | }
45 |
46 | @Before("webLog()")
47 | public void doBefore(JoinPoint joinPoint) throws Throwable {
48 | }
49 |
50 | @AfterReturning(value = "webLog()", returning = "ret")
51 | public void doAfterReturning(Object ret) throws Throwable {
52 | }
53 |
54 | @Around("webLog()")
55 | public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
56 | long startTime = System.currentTimeMillis();
57 | //获取当前请求对象
58 | ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
59 | HttpServletRequest request = attributes.getRequest();
60 | //记录请求信息
61 | WebLog webLog = new WebLog();
62 | Object result = joinPoint.proceed();
63 | Signature signature = joinPoint.getSignature();
64 | MethodSignature methodSignature = (MethodSignature) signature;
65 | Method method = methodSignature.getMethod();
66 | long endTime = System.currentTimeMillis();
67 | String urlStr = request.getRequestURL().toString();
68 | webLog.setBasePath(StrUtil.removeSuffix(urlStr, URLUtil.url(urlStr).getPath()));
69 | webLog.setIp(getIp(request));
70 | webLog.setMethod(request.getMethod());
71 | webLog.setParams(getParameter(method, joinPoint.getArgs()));
72 | webLog.setResponse(result);
73 | webLog.setSpendTime((int) (endTime - startTime));
74 | webLog.setStartTime(startTime);
75 | webLog.setUri(request.getRequestURI());
76 | webLog.setUrl(request.getRequestURL().toString());
77 | LOGGER.info("{}", JSONUtil.parse(webLog));
78 | return result;
79 | }
80 |
81 | /**
82 | * 根据方法和传入的参数获取请求参数
83 | */
84 | private Object getParameter(Method method, Object[] args) {
85 | List