sqlParserList = new ArrayList<>();
39 | // 攻击 SQL 阻断解析器、加入解析链 作用!阻止恶意的全表更新删除
40 | sqlParserList.add(new BlockAttackSqlParser());
41 | paginationInterceptor.setSqlParserList(sqlParserList);
42 | return paginationInterceptor;
43 | }
44 |
45 | /**
46 | * SQL执行效率插件 设置 dev test 环境开启
47 | * @author :LeiGQ
48 | * @date :2019-06-14 10:46
49 | *
50 | */
51 | @Bean
52 | @Profile({"dev","test"})
53 | public PerformanceInterceptor performanceInterceptor() {
54 | final PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
55 | performanceInterceptor.setFormat(true);
56 | performanceInterceptor.setMaxTime(3000);
57 | return new PerformanceInterceptor();
58 | }
59 |
60 | /**
61 | * 乐观锁
62 | * @author :LeiGQ
63 | * @date :2019-06-14 10:55
64 | *
65 | */
66 | @Bean
67 | public OptimisticLockerInterceptor optimisticLockerInterceptor() {
68 | return new OptimisticLockerInterceptor();
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/config/MySessionManager.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.config;
2 |
3 | import org.apache.commons.lang3.StringUtils;
4 | import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
5 | import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
6 | import org.apache.shiro.web.util.WebUtils;
7 |
8 | import javax.servlet.ServletRequest;
9 | import javax.servlet.ServletResponse;
10 | import java.io.Serializable;
11 |
12 | /**
13 | * 自定义session管理
14 | *
15 | * 传统结构项目中,shiro从cookie中读取sessionId以此来维持会话,在前后端分离的项目中(也可在移动APP项目使用),
16 | * 我们选择在ajax的请求头中传递sessionId,因此需要重写shiro获取sessionId的方式。
17 | * 自定义MySessionManager类继承DefaultWebSessionManager类,重写getSessionId方法
18 | * @author :leigq
19 | * @date :2019/7/1 10:52
20 | */
21 | public class MySessionManager extends DefaultWebSessionManager {
22 |
23 | private static final String AUTHORIZATION = "Authorization";
24 |
25 | private static final String REFERENCED_SESSION_ID_SOURCE = "Stateless request";
26 |
27 | @Override
28 | protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
29 | String id = WebUtils.toHttp(request).getHeader(AUTHORIZATION);
30 | //如果请求头中有 Authorization 则其值为sessionId
31 | if (!StringUtils.isEmpty(id)) {
32 | request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, REFERENCED_SESSION_ID_SOURCE);
33 | request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);
34 | request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
35 | return id;
36 | } else {
37 | //否则按默认规则从cookie取sessionId
38 | return super.getSessionId(request, response);
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/config/MyShiroRealm.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.config;
2 |
3 | import com.leigq.www.shiro.domain.entity.Permission;
4 | import com.leigq.www.shiro.domain.entity.Role;
5 | import com.leigq.www.shiro.domain.entity.User;
6 | import com.leigq.www.shiro.service.IPermissionService;
7 | import com.leigq.www.shiro.service.IRoleService;
8 | import com.leigq.www.shiro.service.IUserService;
9 | import lombok.extern.slf4j.Slf4j;
10 | import org.apache.shiro.authc.AuthenticationException;
11 | import org.apache.shiro.authc.AuthenticationInfo;
12 | import org.apache.shiro.authc.AuthenticationToken;
13 | import org.apache.shiro.authc.SimpleAuthenticationInfo;
14 | import org.apache.shiro.authz.AuthorizationInfo;
15 | import org.apache.shiro.authz.SimpleAuthorizationInfo;
16 | import org.apache.shiro.realm.AuthorizingRealm;
17 | import org.apache.shiro.subject.PrincipalCollection;
18 | import org.apache.shiro.util.ByteSource;
19 |
20 | import javax.annotation.Resource;
21 | import java.util.List;
22 | import java.util.Objects;
23 |
24 | /**
25 | * @author :leigq
26 | * @date :2019/6/28 16:31
27 | * @description:自定义 shiroRealm, 主要是重写其认证、授权
28 | */
29 | @Slf4j
30 | public class MyShiroRealm extends AuthorizingRealm {
31 |
32 | @Resource
33 | private IUserService iUserService;
34 |
35 | @Resource
36 | private IRoleService iRoleService;
37 |
38 | @Resource
39 | private IPermissionService iPermissionService;
40 |
41 |
42 | /**
43 | * create by: leigq
44 | * description: 授权
45 | * create time: 2019/7/1 10:32
46 | *
47 | * @return 权限信息,包括角色以及权限
48 | */
49 | @Override
50 | protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
51 | log.warn("开始执行授权操作.......");
52 |
53 | SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
54 | //如果身份认证的时候没有传入User对象,这里只能取到userName
55 | //也就是SimpleAuthenticationInfo构造的时候第一个参数传递需要User对象
56 | User user = (User) principals.getPrimaryPrincipal();
57 |
58 | // 查询用户角色,一个用户可能有多个角色
59 | List roles = iRoleService.getUserRoles(user.getUserId());
60 |
61 | for (Role role : roles) {
62 | authorizationInfo.addRole(role.getRole());
63 | // 根据角色查询权限
64 | List permissions = iPermissionService.getRolePermissions(role.getRoleId());
65 | for (Permission p : permissions) {
66 | authorizationInfo.addStringPermission(p.getPermission());
67 | }
68 | }
69 | return authorizationInfo;
70 | }
71 |
72 | /**
73 | * create by: leigq
74 | * description: 主要是用来进行身份认证的,也就是说验证用户输入的账号和密码是否正确。
75 | * create time: 2019/7/1 09:04
76 | *
77 | * @return 身份验证信息
78 | */
79 | @Override
80 | protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
81 | log.warn("开始进行身份认证......");
82 |
83 | //获取用户的输入的账号.
84 | String userName = (String) token.getPrincipal();
85 |
86 | //通过username从数据库中查找 User对象.
87 | //实际项目中,这里可以根据实际情况做缓存,如果不做,Shiro自己也是有时间间隔机制,2分钟内不会重复执行该方法
88 | User user = iUserService.findByUsername(userName);
89 | if (Objects.isNull(user)) {
90 | return null;
91 | }
92 |
93 | return new SimpleAuthenticationInfo(
94 | // 这里传入的是user对象,比对的是用户名,直接传入用户名也没错,但是在授权部分就需要自己重新从数据库里取权限
95 | user,
96 | // 密码
97 | user.getPassword(),
98 | // salt = username + salt
99 | ByteSource.Util.bytes(user.getCredentialsSalt()),
100 | // realm name
101 | getName()
102 | );
103 | }
104 |
105 | }
106 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/config/ShiroConfig.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.config;
2 |
3 | import lombok.Data;
4 | import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
5 | import org.apache.shiro.mgt.SecurityManager;
6 | import org.apache.shiro.session.mgt.SessionManager;
7 | import org.apache.shiro.session.mgt.eis.JavaUuidSessionIdGenerator;
8 | import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
9 | import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
10 | import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
11 | import org.apache.shiro.web.servlet.SimpleCookie;
12 | import org.crazycake.shiro.RedisCacheManager;
13 | import org.crazycake.shiro.RedisManager;
14 | import org.crazycake.shiro.RedisSessionDAO;
15 | import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
16 | import org.springframework.boot.context.properties.ConfigurationProperties;
17 | import org.springframework.context.annotation.Bean;
18 | import org.springframework.context.annotation.Configuration;
19 |
20 | import java.time.Duration;
21 | import java.util.LinkedHashMap;
22 | import java.util.Map;
23 |
24 | /**
25 | * @author :leigq
26 | * @date :2019/6/28 16:53
27 | * @description:shiro配置
28 | */
29 | @Configuration
30 | @ConfigurationProperties(
31 | prefix = "spring.redis"
32 | )
33 | @Data
34 | public class ShiroConfig {
35 |
36 | private String host = "localhost";
37 | private int port = 6379;
38 | private String password;
39 | private Duration timeout;
40 |
41 | /**
42 | * Filter工厂,设置对应的过滤条件和跳转条件
43 | * create by: leigq
44 | * create time: 2019/7/3 14:29
45 | *
46 | * @return ShiroFilterFactoryBean
47 | */
48 | @Bean
49 | public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
50 |
51 | ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
52 | shiroFilterFactoryBean.setSecurityManager(securityManager);
53 |
54 | // 过滤器链定义映射
55 | Map filterChainDefinitionMap = new LinkedHashMap<>();
56 |
57 | /*
58 | * anon:所有url都都可以匿名访问,authc:所有url都必须认证通过才可以访问;
59 | * 过滤链定义,从上向下顺序执行,authc 应放在 anon 下面
60 | * */
61 | filterChainDefinitionMap.put("/login", "anon");
62 | // 配置不会被拦截的链接 顺序判断,因为前端模板采用了thymeleaf,这里不能直接使用 ("/static/**", "anon")来配置匿名访问,必须配置到每个静态目录
63 | filterChainDefinitionMap.put("/css/**", "anon");
64 | filterChainDefinitionMap.put("/fonts/**", "anon");
65 | filterChainDefinitionMap.put("/img/**", "anon");
66 | filterChainDefinitionMap.put("/js/**", "anon");
67 | filterChainDefinitionMap.put("/html/**", "anon");
68 | // 所有url都必须认证通过才可以访问
69 | filterChainDefinitionMap.put("/**", "authc");
70 |
71 | // 配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了, 位置放在 anon、authc下面
72 | filterChainDefinitionMap.put("/logout", "logout");
73 |
74 | // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
75 | // 配器shirot认登录累面地址,前后端分离中登录累面跳转应由前端路由控制,后台仅返回json数据, 对应LoginController中unauth请求
76 | shiroFilterFactoryBean.setLoginUrl("/un_auth");
77 |
78 | // 登录成功后要跳转的链接, 此项目是前后端分离,故此行注释掉,登录成功之后返回用户基本信息及token给前端
79 | // shiroFilterFactoryBean.setSuccessUrl("/index");
80 |
81 | // 未授权界面, 对应LoginController中 unauthorized 请求
82 | shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");
83 | shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
84 | return shiroFilterFactoryBean;
85 | }
86 |
87 |
88 | /**
89 | * 凭证匹配器(由于我们的密码校验交给Shiro的SimpleAuthenticationInfo进行处理了)
90 | * create by: leigq
91 | * create time: 2019/7/3 14:30
92 | *
93 | * @return HashedCredentialsMatcher
94 | */
95 | @Bean
96 | public HashedCredentialsMatcher hashedCredentialsMatcher() {
97 | HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
98 | // 散列算法:这里使用MD5算法;
99 | hashedCredentialsMatcher.setHashAlgorithmName("md5");
100 | // 散列的次数,比如散列两次,相当于 md5(md5(""));
101 | hashedCredentialsMatcher.setHashIterations(2);
102 | return hashedCredentialsMatcher;
103 | }
104 |
105 | /**
106 | * 将自己的验证方式加入容器
107 | * create by: leigq
108 | * create time: 2019/7/3 14:30
109 | *
110 | * @return MyShiroRealm
111 | */
112 | @Bean
113 | public MyShiroRealm myShiroRealm() {
114 | MyShiroRealm myShiroRealm = new MyShiroRealm();
115 | myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
116 | return myShiroRealm;
117 | }
118 |
119 | /**
120 | * RedisSessionDAO shiro sessionDao层的实现 通过redis, 使用的是shiro-redis开源插件
121 | * create by: leigq
122 | * create time: 2019/7/3 14:30
123 | *
124 | * @return RedisSessionDAO
125 | */
126 | @Bean
127 | public RedisSessionDAO redisSessionDAO() {
128 | RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
129 | redisSessionDAO.setRedisManager(redisManager());
130 | redisSessionDAO.setSessionIdGenerator(sessionIdGenerator());
131 | redisSessionDAO.setExpire(1800);
132 | return redisSessionDAO;
133 | }
134 |
135 | /**
136 | * Session ID 生成器
137 | *
138 | * create by: leigq
139 | *
140 | * create time: 2019/7/3 16:08
141 | *
142 | * @return JavaUuidSessionIdGenerator
143 | */
144 | @Bean
145 | public JavaUuidSessionIdGenerator sessionIdGenerator() {
146 | return new JavaUuidSessionIdGenerator();
147 | }
148 |
149 | /**
150 | * 自定义sessionManager
151 | * create by: leigq
152 | * create time: 2019/7/3 14:31
153 | *
154 | * @return SessionManager
155 | */
156 | @Bean
157 | public SessionManager sessionManager() {
158 | MySessionManager mySessionManager = new MySessionManager();
159 | mySessionManager.setSessionDAO(redisSessionDAO());
160 | return mySessionManager;
161 | }
162 |
163 | /**
164 | * 配置shiro redisManager, 使用的是shiro-redis开源插件
165 | *
166 | * create by: leigq
167 | *
168 | * create time: 2019/7/3 14:33
169 | *
170 | * @return RedisManager
171 | */
172 | private RedisManager redisManager() {
173 | RedisManager redisManager = new RedisManager();
174 | redisManager.setHost(host);
175 | redisManager.setPort(port);
176 | redisManager.setTimeout((int) timeout.toMillis());
177 | redisManager.setPassword(password);
178 | return redisManager;
179 | }
180 |
181 | /**
182 | * cacheManager 缓存 redis实现, 使用的是shiro-redis开源插件
183 | *
184 | * create by: leigq
185 | *
186 | * create time: 2019/7/3 14:33
187 | *
188 | * @return RedisCacheManager
189 | */
190 | @Bean
191 | public RedisCacheManager cacheManager() {
192 | RedisCacheManager redisCacheManager = new RedisCacheManager();
193 | redisCacheManager.setRedisManager(redisManager());
194 | // 必须要设置主键名称,shiro-redis 插件用过这个缓存用户信息
195 | redisCacheManager.setPrincipalIdFieldName("userId");
196 | return redisCacheManager;
197 | }
198 |
199 | /**
200 | * create by: leigq
201 | * description: 权限管理,配置主要是Realm的管理认证
202 | * create time: 2019/7/1 10:09
203 | *
204 | * @return SecurityManager
205 | */
206 | @Bean
207 | public SecurityManager securityManager() {
208 | DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
209 | securityManager.setRealm(myShiroRealm());
210 | // 自定义session管理 使用redis
211 | securityManager.setSessionManager(sessionManager());
212 | // 自定义缓存实现 使用redis
213 | securityManager.setCacheManager(cacheManager());
214 | return securityManager;
215 | }
216 |
217 | /*
218 | * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
219 | * 配置以下两个bean(DefaultAdvisorAutoProxyCreator(可选)和AuthorizationAttributeSourceAdvisor)即可实现此功能
220 | */
221 | @Bean
222 | public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator() {
223 | DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
224 | advisorAutoProxyCreator.setProxyTargetClass(true);
225 | return advisorAutoProxyCreator;
226 | }
227 |
228 | @Bean
229 | public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
230 | AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
231 | authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
232 | return authorizationAttributeSourceAdvisor;
233 | }
234 |
235 | @Bean
236 | public SimpleCookie cookie() {
237 | // cookie的name,对应的默认是 JSESSIONID
238 | SimpleCookie cookie = new SimpleCookie("SHARE_JSESSIONID");
239 | cookie.setHttpOnly(true);
240 | // path为 / 用于多个系统共享 JSESSIONID
241 | cookie.setPath("/");
242 | return cookie;
243 | }
244 |
245 | /* 此项目使用 shiro 场景为前后端分离项目,这里先注释掉,统一异常处理已在 GlobalExceptionHand.java 中实现 */
246 | /**
247 | * create by: leigq
248 | * description: 异常处理, 详见:https://www.cnblogs.com/libra0920/p/6289848.html
249 | * create time: 2019/7/1 10:28
250 | * @return SimpleMappingExceptionResolver
251 | */
252 | // @Bean(name = "simpleMappingExceptionResolver")
253 | // public SimpleMappingExceptionResolver createSimpleMappingExceptionResolver() {
254 | // SimpleMappingExceptionResolver r = new SimpleMappingExceptionResolver();
255 | // Properties mappings = new Properties();
256 | // mappings.setProperty("DatabaseException", "databaseError");//数据库异常处理
257 | // mappings.setProperty("UnauthorizedException", "/user/403");
258 | // r.setExceptionMappings(mappings); // None by default
259 | // r.setDefaultErrorView("error"); // No default
260 | // r.setExceptionAttribute("exception"); // Default is "exception"
261 | // //r.setWarnLogCategory("example.MvcLogger"); // No default
262 | // return r;
263 | // }
264 | }
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/controller/LoginController.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.controller;
2 |
3 | import com.leigq.www.shiro.bean.CacheUser;
4 | import com.leigq.www.shiro.bean.Response;
5 | import com.leigq.www.shiro.domain.entity.User;
6 | import com.leigq.www.shiro.service.IUserService;
7 | import lombok.extern.slf4j.Slf4j;
8 | import org.apache.commons.lang3.StringUtils;
9 | import org.springframework.http.HttpStatus;
10 | import org.springframework.web.bind.annotation.PostMapping;
11 | import org.springframework.web.bind.annotation.RequestMapping;
12 | import org.springframework.web.bind.annotation.RestController;
13 |
14 | import javax.annotation.Resource;
15 |
16 | /**
17 | * @author :leigq
18 | * @date :2019/6/28 16:55
19 | * @description:登录Controller
20 | */
21 | @Slf4j
22 | @RestController
23 | public class LoginController {
24 |
25 | @Resource
26 | private IUserService iUserService;
27 |
28 | @Resource
29 | private Response response;
30 |
31 | /**
32 | * create by: leigq
33 | * description: 登录
34 | * create time: 2019/6/28 17:11
35 | *
36 | * @return 登录结果
37 | */
38 | @PostMapping("/login")
39 | public Response login(User user) {
40 | log.warn("进入登录.....");
41 |
42 | String userName = user.getUserName();
43 | String password = user.getPassword();
44 |
45 | if (StringUtils.isBlank(userName)) {
46 | return response.failure("用户名为空!");
47 | }
48 |
49 | if (StringUtils.isBlank(password)) {
50 | return response.failure("密码为空!");
51 | }
52 |
53 | CacheUser loginUser = iUserService.login(userName, password);
54 | // 登录成功返回用户信息
55 | return response.success("登录成功!", loginUser);
56 | }
57 |
58 | /**
59 | * create by: leigq
60 | * description: 登出
61 | * create time: 2019/6/28 17:37
62 | */
63 | @RequestMapping("/logout")
64 | public Response logOut() {
65 | iUserService.logout();
66 | return response.success("登出成功!");
67 | }
68 |
69 | /**
70 | * 未登录,shiro应重定向到登录界面,此处返回未登录状态信息由前端控制跳转页面
71 | *
72 | * create by: leigq
73 | *
74 | * create time: 2019/7/3 14:53
75 | * @return
76 | */
77 | @RequestMapping("/un_auth")
78 | public Response unAuth() {
79 | return response.failure(HttpStatus.UNAUTHORIZED, "用户未登录!", null);
80 | }
81 |
82 | /**
83 | * 未授权,无权限,此处返回未授权状态信息由前端控制跳转页面
84 | *
85 | * create by: leigq
86 | *
87 | * create time: 2019/7/3 14:53
88 | * @return
89 | */
90 | @RequestMapping("/unauthorized")
91 | public Response unauthorized() {
92 | return response.failure(HttpStatus.FORBIDDEN, "用户无权限!", null);
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/controller/PermissionController.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.controller;
2 |
3 |
4 | import org.springframework.web.bind.annotation.RequestMapping;
5 | import org.springframework.web.bind.annotation.RestController;
6 |
7 | /**
8 | *
9 | * 前端控制器
10 | *
11 | *
12 | * @author leigq
13 | * @since 2019-06-28
14 | */
15 | @RestController
16 | @RequestMapping("/sys/permission")
17 | public class PermissionController {
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/controller/RoleController.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.controller;
2 |
3 |
4 | import org.springframework.web.bind.annotation.RequestMapping;
5 | import org.springframework.web.bind.annotation.RestController;
6 |
7 | /**
8 | *
9 | * 前端控制器
10 | *
11 | *
12 | * @author leigq
13 | * @since 2019-06-28
14 | */
15 | @RestController
16 | @RequestMapping("/sys/role")
17 | public class RoleController {
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/controller/RolePermissionController.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.controller;
2 |
3 |
4 | import org.springframework.web.bind.annotation.RequestMapping;
5 | import org.springframework.web.bind.annotation.RestController;
6 |
7 | /**
8 | *
9 | * 前端控制器
10 | *
11 | *
12 | * @author leigq
13 | * @since 2019-06-28
14 | */
15 | @RestController
16 | @RequestMapping("/sys/role-permission")
17 | public class RolePermissionController {
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/controller/UserController.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.controller;
2 |
3 |
4 | import com.leigq.www.shiro.bean.Response;
5 | import com.leigq.www.shiro.domain.entity.User;
6 | import com.leigq.www.shiro.service.IUserService;
7 | import org.apache.shiro.authz.annotation.RequiresPermissions;
8 | import org.springframework.beans.factory.annotation.Autowired;
9 | import org.springframework.web.bind.annotation.*;
10 |
11 | import java.util.List;
12 |
13 | /**
14 | *
15 | * 前端控制器
16 | *
17 | *
18 | * @author leigq
19 | * @since 2019-06-28
20 | */
21 | @RestController
22 | @RequestMapping("/user")
23 | public class UserController {
24 |
25 | @Autowired
26 | private IUserService iUserService;
27 |
28 | @Autowired
29 | private Response response;
30 |
31 | /**
32 | * 用户查询.
33 | * @return
34 | */
35 | @GetMapping("/userList")
36 | @RequiresPermissions("user:view")//权限管理;
37 | public Response listUsers(){
38 | List users = iUserService.listUsers();
39 | return response.success("查询成功!", users);
40 | }
41 |
42 | /**
43 | * 用户添加;
44 | * @return
45 | */
46 | @PostMapping("/userAdd")
47 | @RequiresPermissions("user:add")//权限管理;
48 | public String userInfoAdd(){
49 | return "userAdd";
50 | }
51 |
52 | /**
53 | * 用户删除;
54 | * @return
55 | */
56 | @DeleteMapping("/userDel")
57 | @RequiresPermissions("user:del")//权限管理;
58 | public String userDel(){
59 | return "userDel";
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/controller/UserRoleController.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.controller;
2 |
3 |
4 | import org.springframework.web.bind.annotation.RequestMapping;
5 | import org.springframework.web.bind.annotation.RestController;
6 |
7 | /**
8 | *
9 | * 前端控制器
10 | *
11 | *
12 | * @author leigq
13 | * @since 2019-06-28
14 | */
15 | @RestController
16 | @RequestMapping("/sys/user-role")
17 | public class UserRoleController {
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/domain/entity/Permission.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.domain.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableField;
5 | import com.baomidou.mybatisplus.annotation.TableId;
6 | import com.baomidou.mybatisplus.annotation.TableName;
7 | import lombok.Data;
8 | import lombok.EqualsAndHashCode;
9 | import lombok.experimental.Accessors;
10 |
11 | import java.io.Serializable;
12 |
13 | /**
14 | *
15 | *
16 | *
17 | *
18 | * @author leigq
19 | * @since 2019-06-28
20 | */
21 | @Data
22 | @EqualsAndHashCode(callSuper = false)
23 | @Accessors(chain = true)
24 | @TableName("sys_permission")
25 | public class Permission implements Serializable {
26 |
27 | private static final long serialVersionUID = 1L;
28 |
29 | @TableId(value = "permissionId", type = IdType.AUTO)
30 | private Integer permissionId;
31 |
32 | @TableField("available")
33 | private Boolean available;
34 |
35 | @TableField("parentId")
36 | private Long parentId;
37 |
38 | @TableField("parentIds")
39 | private String parentIds;
40 |
41 | @TableField("permission")
42 | private String permission;
43 |
44 | @TableField("permissionName")
45 | private String permissionName;
46 |
47 | @TableField("resourceType")
48 | private String resourceType;
49 |
50 | @TableField("url")
51 | private String url;
52 |
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/domain/entity/Role.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.domain.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import com.baomidou.mybatisplus.annotation.TableName;
6 | import lombok.Data;
7 | import lombok.EqualsAndHashCode;
8 | import lombok.experimental.Accessors;
9 |
10 | import java.io.Serializable;
11 |
12 | /**
13 | *
14 | *
15 | *
16 | *
17 | * @author leigq
18 | * @since 2019-06-28
19 | */
20 | @Data
21 | @EqualsAndHashCode(callSuper = false)
22 | @Accessors(chain = true)
23 | @TableName("sys_role")
24 | public class Role implements Serializable {
25 |
26 | private static final long serialVersionUID = 1L;
27 |
28 | @TableId(value = "roleId", type = IdType.AUTO)
29 | private Integer roleId;
30 |
31 | private Boolean available;
32 |
33 | private String description;
34 |
35 | private String role;
36 |
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/domain/entity/RolePermission.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.domain.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.TableField;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import com.baomidou.mybatisplus.annotation.TableName;
6 | import lombok.Data;
7 | import lombok.EqualsAndHashCode;
8 | import lombok.experimental.Accessors;
9 |
10 | import java.io.Serializable;
11 |
12 | /**
13 | *
14 | *
15 | *
16 | *
17 | * @author leigq
18 | * @since 2019-06-28
19 | */
20 | @Data
21 | @EqualsAndHashCode(callSuper = false)
22 | @Accessors(chain = true)
23 | @TableName("sys_role_permission")
24 | public class RolePermission implements Serializable {
25 |
26 | private static final long serialVersionUID = 1L;
27 |
28 | @TableId
29 | private Long id;
30 |
31 | @TableField("permissionId")
32 | private Integer permissionId;
33 |
34 | @TableField("roleId")
35 | private Integer roleId;
36 |
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/domain/entity/User.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.domain.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.IdType;
4 | import com.baomidou.mybatisplus.annotation.TableField;
5 | import com.baomidou.mybatisplus.annotation.TableId;
6 | import com.baomidou.mybatisplus.annotation.TableName;
7 | import lombok.Data;
8 | import lombok.EqualsAndHashCode;
9 | import lombok.experimental.Accessors;
10 | import org.crazycake.shiro.AuthCachePrincipal;
11 |
12 | import java.io.Serializable;
13 | import java.time.LocalDate;
14 | import java.time.LocalDateTime;
15 | import java.util.Date;
16 |
17 | /**
18 | *
19 | *
20 | *
21 | *
22 | * @author leigq
23 | * @since 2019-06-28
24 | */
25 | @Data
26 | @EqualsAndHashCode(callSuper = false)
27 | @Accessors(chain = true)
28 | @TableName("sys_user")
29 | public class User implements Serializable {
30 |
31 | private static final long serialVersionUID = 1L;
32 |
33 | @TableId(value = "userId", type = IdType.AUTO)
34 | private Integer userId;
35 |
36 | @TableField("createTime")
37 | private Date createTime;
38 |
39 | private String email;
40 |
41 | @TableField("expiredDate")
42 | private Date expiredDate;
43 |
44 | private String name;
45 |
46 | private String password;
47 |
48 | private String salt;
49 |
50 | private Integer state;
51 |
52 | @TableField("userName")
53 | private String userName;
54 |
55 | /**
56 | * 密码盐. 重新对盐重新进行了定义,用户名+salt,这样就不容易被破解,可以采用多种方式定义加盐
57 | *
58 | * @return
59 | */
60 | public String getCredentialsSalt() {
61 | return this.userName + this.salt;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/domain/entity/UserRole.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.domain.entity;
2 |
3 | import com.baomidou.mybatisplus.annotation.TableField;
4 | import com.baomidou.mybatisplus.annotation.TableId;
5 | import com.baomidou.mybatisplus.annotation.TableName;
6 | import lombok.Data;
7 | import lombok.EqualsAndHashCode;
8 | import lombok.experimental.Accessors;
9 |
10 | import java.io.Serializable;
11 |
12 | /**
13 | *
14 | *
15 | *
16 | *
17 | * @author leigq
18 | * @since 2019-06-28
19 | */
20 | @Data
21 | @EqualsAndHashCode(callSuper = false)
22 | @Accessors(chain = true)
23 | @TableName("sys_user_role")
24 | public class UserRole implements Serializable {
25 |
26 | private static final long serialVersionUID = 1L;
27 |
28 | @TableId
29 | private Long id;
30 |
31 | @TableField("userId")
32 | private Integer userId;
33 |
34 | @TableField("roleId")
35 | private Integer roleId;
36 |
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/domain/mapper/PermissionMapper.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.domain.mapper;
2 |
3 |
4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
5 | import com.leigq.www.shiro.domain.entity.Permission;
6 | import org.apache.ibatis.annotations.Mapper;
7 | import org.apache.ibatis.annotations.Param;
8 |
9 | import java.util.List;
10 |
11 | /**
12 | *
13 | * Mapper 接口
14 | *
15 | *
16 | * @author leigq
17 | * @since 2019-06-28
18 | */
19 | public interface PermissionMapper extends BaseMapper {
20 |
21 | List getRolePermissions(@Param("roleId") Integer roleId);
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/domain/mapper/RoleMapper.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.domain.mapper;
2 |
3 |
4 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
5 | import com.leigq.www.shiro.domain.entity.Role;
6 | import org.apache.ibatis.annotations.Mapper;
7 | import org.apache.ibatis.annotations.Param;
8 |
9 | import java.util.List;
10 |
11 | /**
12 | *
13 | * Mapper 接口
14 | *
15 | *
16 | * @author leigq
17 | * @since 2019-06-28
18 | */
19 | public interface RoleMapper extends BaseMapper {
20 |
21 | List getUserRoles(@Param("userId") Integer userId);
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/domain/mapper/RolePermissionMapper.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.domain.mapper;
2 |
3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 | import com.leigq.www.shiro.domain.entity.RolePermission;
5 |
6 | /**
7 | *
8 | * Mapper 接口
9 | *
10 | *
11 | * @author leigq
12 | * @since 2019-06-28
13 | */
14 | public interface RolePermissionMapper extends BaseMapper {
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/domain/mapper/UserMapper.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.domain.mapper;
2 |
3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 | import com.leigq.www.shiro.domain.entity.User;
5 |
6 | /**
7 | *
8 | * Mapper 接口
9 | *
10 | *
11 | * @author leigq
12 | * @since 2019-06-28
13 | */
14 | public interface UserMapper extends BaseMapper {
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/domain/mapper/UserRoleMapper.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.domain.mapper;
2 |
3 | import com.baomidou.mybatisplus.core.mapper.BaseMapper;
4 | import com.leigq.www.shiro.domain.entity.UserRole;
5 |
6 | /**
7 | *
8 | * Mapper 接口
9 | *
10 | *
11 | * @author leigq
12 | * @since 2019-06-28
13 | */
14 | public interface UserRoleMapper extends BaseMapper {
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/service/IPermissionService.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.service;
2 |
3 | import com.baomidou.mybatisplus.extension.service.IService;
4 | import com.leigq.www.shiro.domain.entity.Permission;
5 |
6 | import java.util.List;
7 |
8 | /**
9 | *
10 | * 服务类
11 | *
12 | *
13 | * @author leigq
14 | * @since 2019-06-28
15 | */
16 | public interface IPermissionService extends IService {
17 |
18 | List getRolePermissions(Integer roleId);
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/service/IRolePermissionService.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.service;
2 |
3 | import com.baomidou.mybatisplus.extension.service.IService;
4 | import com.leigq.www.shiro.domain.entity.RolePermission;
5 |
6 | /**
7 | *
8 | * 服务类
9 | *
10 | *
11 | * @author leigq
12 | * @since 2019-06-28
13 | */
14 | public interface IRolePermissionService extends IService {
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/service/IRoleService.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.service;
2 |
3 | import com.baomidou.mybatisplus.extension.service.IService;
4 | import com.leigq.www.shiro.domain.entity.Role;
5 | import org.apache.ibatis.annotations.Mapper;
6 | import org.mybatis.spring.annotation.MapperScan;
7 |
8 | import java.util.List;
9 |
10 | /**
11 | *
12 | * 服务类
13 | *
14 | *
15 | * @author leigq
16 | * @since 2019-06-28
17 | */
18 | public interface IRoleService extends IService {
19 | List getUserRoles(Integer userId);
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/service/IUserRoleService.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.service;
2 |
3 | import com.baomidou.mybatisplus.extension.service.IService;
4 | import com.leigq.www.shiro.domain.entity.UserRole;
5 |
6 | /**
7 | *
8 | * 服务类
9 | *
10 | *
11 | * @author leigq
12 | * @since 2019-06-28
13 | */
14 | public interface IUserRoleService extends IService {
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/service/IUserService.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.service;
2 |
3 | import com.baomidou.mybatisplus.extension.service.IService;
4 | import com.leigq.www.shiro.bean.CacheUser;
5 | import com.leigq.www.shiro.domain.entity.User;
6 |
7 | import java.util.List;
8 |
9 | /**
10 | *
11 | * 服务类
12 | *
13 | *
14 | * @author leigq
15 | * @since 2019-06-28
16 | */
17 | public interface IUserService extends IService {
18 |
19 | /**
20 | * create by: leigq
21 | * description: 根据用户名获取用户
22 | * create time: 2019/6/28 16:19
23 | * @param userName 用户名
24 | * @return 用户
25 | */
26 | User findByUsername(String userName);
27 |
28 | /**
29 | * create by: leigq
30 | * description: 登录
31 | * create time: 2019/6/28 16:26
32 | * @param userName 用户名
33 | * @param password 密码
34 | * @return 用户信息
35 | */
36 | CacheUser login(String userName, String password);
37 |
38 |
39 | /**
40 | * create by: leigq
41 | * description: 登出
42 | * create time: 2019/6/28 16:30
43 | */
44 | void logout();
45 |
46 | List listUsers();
47 | }
48 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/service/impl/PermissionServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.service.impl;
2 |
3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
4 | import com.leigq.www.shiro.domain.entity.Permission;
5 | import com.leigq.www.shiro.domain.mapper.PermissionMapper;
6 | import com.leigq.www.shiro.service.IPermissionService;
7 | import org.springframework.stereotype.Service;
8 |
9 | import javax.annotation.Resource;
10 | import java.util.List;
11 |
12 | /**
13 | *
14 | * 服务实现类
15 | *
16 | *
17 | * @author leigq
18 | * @since 2019-06-28
19 | */
20 | @Service
21 | public class PermissionServiceImpl extends ServiceImpl implements IPermissionService {
22 |
23 | @Resource
24 | private PermissionMapper permissionMapper;
25 |
26 | @Override
27 | public List getRolePermissions(Integer roleId) {
28 | return permissionMapper.getRolePermissions(roleId);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/service/impl/RolePermissionServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.service.impl;
2 |
3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
4 | import com.leigq.www.shiro.domain.entity.RolePermission;
5 | import com.leigq.www.shiro.domain.mapper.RolePermissionMapper;
6 | import com.leigq.www.shiro.service.IRolePermissionService;
7 | import org.springframework.stereotype.Service;
8 |
9 | /**
10 | *
11 | * 服务实现类
12 | *
13 | *
14 | * @author leigq
15 | * @since 2019-06-28
16 | */
17 | @Service
18 | public class RolePermissionServiceImpl extends ServiceImpl implements IRolePermissionService {
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/service/impl/RoleServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.service.impl;
2 |
3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
4 | import com.leigq.www.shiro.domain.entity.Role;
5 | import com.leigq.www.shiro.domain.mapper.RoleMapper;
6 | import com.leigq.www.shiro.service.IRoleService;
7 | import org.springframework.beans.factory.annotation.Autowired;
8 | import org.springframework.stereotype.Service;
9 |
10 | import javax.annotation.Resource;
11 | import java.util.List;
12 |
13 | /**
14 | *
15 | * 服务实现类
16 | *
17 | *
18 | * @author leigq
19 | * @since 2019-06-28
20 | */
21 | @Service
22 | public class RoleServiceImpl extends ServiceImpl implements IRoleService {
23 |
24 | @Resource
25 | private RoleMapper roleMapper;
26 |
27 | @Override
28 | public List getUserRoles(Integer userId) {
29 | return roleMapper.getUserRoles(userId);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/service/impl/UserRoleServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.service.impl;
2 |
3 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
4 | import com.leigq.www.shiro.domain.entity.UserRole;
5 | import com.leigq.www.shiro.domain.mapper.UserRoleMapper;
6 | import com.leigq.www.shiro.service.IUserRoleService;
7 | import org.springframework.stereotype.Service;
8 |
9 | /**
10 | *
11 | * 服务实现类
12 | *
13 | *
14 | * @author leigq
15 | * @since 2019-06-28
16 | */
17 | @Service
18 | public class UserRoleServiceImpl extends ServiceImpl implements IUserRoleService {
19 |
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/service/impl/UserServiceImpl.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.service.impl;
2 |
3 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
4 | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
5 | import com.leigq.www.shiro.bean.CacheUser;
6 | import com.leigq.www.shiro.domain.entity.User;
7 | import com.leigq.www.shiro.domain.mapper.UserMapper;
8 | import com.leigq.www.shiro.service.IUserService;
9 | import com.leigq.www.shiro.web.exception.LoginException;
10 | import lombok.extern.slf4j.Slf4j;
11 | import org.apache.shiro.SecurityUtils;
12 | import org.apache.shiro.authc.AuthenticationException;
13 | import org.apache.shiro.authc.IncorrectCredentialsException;
14 | import org.apache.shiro.authc.UnknownAccountException;
15 | import org.apache.shiro.authc.UsernamePasswordToken;
16 | import org.apache.shiro.subject.Subject;
17 | import org.springframework.beans.BeanUtils;
18 | import org.springframework.stereotype.Service;
19 |
20 | import java.util.List;
21 |
22 | /**
23 | *
24 | * 服务实现类
25 | *
26 | *
27 | * @author leigq
28 | * @since 2019-06-28
29 | */
30 | @Service
31 | @Slf4j
32 | public class UserServiceImpl extends ServiceImpl implements IUserService {
33 |
34 | @Override
35 | public User findByUsername(String username) {
36 | return baseMapper.selectOne(
37 | new LambdaQueryWrapper().eq(User::getUserName, username)
38 | );
39 | }
40 |
41 | @Override
42 | public CacheUser login(String userName, String password) {
43 |
44 | // 获取Subject实例对象,用户实例
45 | Subject currentUser = SecurityUtils.getSubject();
46 |
47 | // 将用户名和密码封装到UsernamePasswordToken
48 | UsernamePasswordToken token = new UsernamePasswordToken(userName, password);
49 |
50 | CacheUser cacheUser;
51 |
52 | // 4、认证
53 | try {
54 | // 传到 MyShiroRealm 类中的方法进行认证
55 | currentUser.login(token);
56 | // 构建缓存用户信息返回给前端
57 | User user = (User) currentUser.getPrincipals().getPrimaryPrincipal();
58 | cacheUser = CacheUser.builder()
59 | .token(currentUser.getSession().getId().toString())
60 | .build();
61 | BeanUtils.copyProperties(user, cacheUser);
62 | log.warn("CacheUser is {}", cacheUser.toString());
63 | } catch (UnknownAccountException e) {
64 | log.error("账户不存在异常:", e);
65 | throw new LoginException("账号不存在!", e);
66 | } catch (IncorrectCredentialsException e) {
67 | log.error("凭据错误(密码错误)异常:", e);
68 | throw new LoginException("密码不正确!", e);
69 | } catch (AuthenticationException e) {
70 | log.error("身份验证异常:", e);
71 | throw new LoginException("用户验证失败!", e);
72 | }
73 | return cacheUser;
74 | }
75 |
76 | @Override
77 | public void logout() {
78 | Subject subject = SecurityUtils.getSubject();
79 | subject.logout();
80 | }
81 |
82 | @Override
83 | public List listUsers() {
84 | return baseMapper.selectList(new LambdaQueryWrapper<>());
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/util/CodeGeneratorUtils.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.util;
2 |
3 | import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
4 | import com.baomidou.mybatisplus.core.toolkit.StringPool;
5 | import com.baomidou.mybatisplus.generator.AutoGenerator;
6 | import com.baomidou.mybatisplus.generator.InjectionConfig;
7 | import com.baomidou.mybatisplus.generator.config.*;
8 | import com.baomidou.mybatisplus.generator.config.po.TableInfo;
9 | import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
10 | import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
11 | import org.apache.commons.lang3.StringUtils;
12 | import org.springframework.beans.factory.annotation.Autowired;
13 | import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
14 |
15 | import java.sql.Driver;
16 | import java.util.*;
17 |
18 | /**
19 | * 代码生成器
20 | *
21 | * AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。
22 | *
23 | * 详见:https://mp.baomidou.com/guide/generator.html
24 | *
25 | * 创建人:LeiGQ
26 | * 创建时间:2019-06-14 11:03
27 | *
28 | * 修改人:
29 | * 修改时间:
30 | * 修改备注:
31 | *
32 | */
33 | public class CodeGeneratorUtils {
34 |
35 | private static final String AUTHOR = "leigq";
36 | private static final String HOST = "127.0.0.1";
37 | private static final String DRIVER_CLASS_NAME = "com.mysql.cj.jdbc.Driver";
38 | private static final String DATABASE_NAME = "shiro";
39 | private static final String DATABASE_USERNAME = "root";
40 | private static final String DATABASE_PASSWORD = "123456";
41 | private static final String PARENT_PACKAGE = "com.leigq.www.shiro";
42 |
43 | /**
44 | *
45 | * 读取控制台内容
46 | *
47 | */
48 | private static String scanner(String tip) {
49 | Scanner scanner = new Scanner(System.in);
50 | System.out.println(("请输入" + tip + ":"));
51 | if (scanner.hasNext()) {
52 | String ipt = scanner.next();
53 | if (StringUtils.isNotEmpty(ipt)) {
54 | return ipt;
55 | }
56 | }
57 | throw new MybatisPlusException("请输入正确的" + tip + "!");
58 | }
59 |
60 |
61 | public static void main(String[] args) {
62 | // 代码生成器
63 | AutoGenerator mpg = new AutoGenerator();
64 |
65 | // 全局配置
66 | GlobalConfig gc = new GlobalConfig();
67 | String projectPath = System.getProperty("user.dir");
68 | gc.setOutputDir(projectPath + "/src/main/java");
69 | gc.setAuthor(AUTHOR);
70 | gc.setOpen(false);
71 | // gc.setSwagger2(true);
72 | mpg.setGlobalConfig(gc);
73 |
74 | // 数据源配置
75 | DataSourceConfig dsc = new DataSourceConfig();
76 | dsc.setUrl(String.format("jdbc:mysql://%s:3306/%s?useUnicode=true&useSSL=false&characterEncoding=utf8&serverTimezone=UTC", HOST, DATABASE_NAME));
77 | // dsc.setSchemaName("public");
78 | dsc.setDriverName(DRIVER_CLASS_NAME);
79 | dsc.setUsername(DATABASE_USERNAME);
80 | dsc.setPassword(DATABASE_PASSWORD);
81 | mpg.setDataSource(dsc);
82 |
83 | // 包配置
84 | PackageConfig pc = new PackageConfig();
85 | pc.setModuleName(scanner("模块名"));
86 | pc.setParent(PARENT_PACKAGE);
87 | mpg.setPackageInfo(pc);
88 |
89 | // 自定义配置
90 | InjectionConfig cfg = new InjectionConfig() {
91 | @Override
92 | public void initMap() {
93 | // to do nothing
94 | }
95 | };
96 |
97 | // 如果模板引擎是 freemarker
98 | String templatePath = "/templates/mapper.xml.ftl";
99 | // 如果模板引擎是 velocity
100 | // String templatePath = "/templates/mapper.xml.vm";
101 |
102 | // 自定义输出配置
103 | List focList = new ArrayList<>();
104 | // 自定义配置会被优先输出
105 | focList.add(new FileOutConfig(templatePath) {
106 | @Override
107 | public String outputFile(TableInfo tableInfo) {
108 | // 自定义输出文件名 , 如果你 Entity 设置了前后缀、此处注意 xml 的名称会跟着发生变化!!
109 | return projectPath + "/src/main/resources/mapper/" + pc.getModuleName()
110 | + "/" + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
111 | }
112 | });
113 | /*
114 | cfg.setFileCreate(new IFileCreate() {
115 | @Override
116 | public boolean isCreate(ConfigBuilder configBuilder, FileType fileType, String filePath) {
117 | // 判断自定义文件夹是否需要创建
118 | checkDir("调用默认方法创建的目录");
119 | return false;
120 | }
121 | });
122 | */
123 | cfg.setFileOutConfigList(focList);
124 | mpg.setCfg(cfg);
125 |
126 | // 配置模板
127 | TemplateConfig templateConfig = new TemplateConfig();
128 |
129 | // 配置自定义输出模板
130 | //指定自定义模板路径,注意不要带上.ftl/.vm, 会根据使用的模板引擎自动识别
131 | // templateConfig.setEntity("templates/entity2.java");
132 | // templateConfig.setService();
133 | // templateConfig.setController();
134 |
135 | templateConfig.setXml(null);
136 | mpg.setTemplate(templateConfig);
137 |
138 | // 策略配置
139 | StrategyConfig strategy = new StrategyConfig();
140 | strategy.setNaming(NamingStrategy.underline_to_camel);
141 | strategy.setColumnNaming(NamingStrategy.underline_to_camel);
142 | // strategy.setSuperEntityClass("com.baomidou.ant.common.BaseEntity");
143 | strategy.setEntityLombokModel(true);
144 | strategy.setRestControllerStyle(true);
145 | // strategy.setSuperControllerClass("com.baomidou.ant.common.BaseController");
146 | strategy.setInclude(scanner("表名,多个英文逗号分割").split(","));
147 | strategy.setSuperEntityColumns("id");
148 | strategy.setControllerMappingHyphenStyle(true);
149 | strategy.setTablePrefix(pc.getModuleName() + "_");
150 | mpg.setStrategy(strategy);
151 | mpg.setTemplateEngine(new FreemarkerTemplateEngine());
152 | mpg.execute();
153 | }
154 |
155 | }
156 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/web/GlobalExceptionHand.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.web;
2 |
3 |
4 | import com.leigq.www.shiro.bean.Response;
5 | import com.leigq.www.shiro.web.exception.LoginException;
6 | import lombok.extern.slf4j.Slf4j;
7 | import org.apache.shiro.authz.UnauthorizedException;
8 | import org.springframework.http.HttpStatus;
9 | import org.springframework.http.converter.HttpMessageNotReadableException;
10 | import org.springframework.validation.BindException;
11 | import org.springframework.validation.BindingResult;
12 | import org.springframework.validation.FieldError;
13 | import org.springframework.web.HttpMediaTypeNotSupportedException;
14 | import org.springframework.web.HttpRequestMethodNotSupportedException;
15 | import org.springframework.web.bind.MethodArgumentNotValidException;
16 | import org.springframework.web.bind.MissingServletRequestParameterException;
17 | import org.springframework.web.bind.annotation.ExceptionHandler;
18 | import org.springframework.web.bind.annotation.ResponseStatus;
19 | import org.springframework.web.bind.annotation.RestControllerAdvice;
20 | import org.springframework.web.multipart.MaxUploadSizeExceededException;
21 | import org.springframework.web.servlet.config.annotation.EnableWebMvc;
22 |
23 | import javax.management.ServiceNotFoundException;
24 | import javax.validation.ConstraintViolation;
25 | import javax.validation.ConstraintViolationException;
26 | import javax.validation.ValidationException;
27 | import java.util.List;
28 | import java.util.Set;
29 |
30 | /**
31 | * 全局异常处理
32 | *
33 | * 创建人:LeiGQ
34 | * 创建时间:2019-05-14 17:09
35 | *
36 | * 修改人:
37 | * 修改时间:
38 | * 修改备注:
39 | *
40 | */
41 | @EnableWebMvc
42 | @RestControllerAdvice
43 | @Slf4j
44 | public class GlobalExceptionHand {
45 |
46 | /**
47 | * 400 - Bad Request
48 | */
49 | @ResponseStatus(HttpStatus.BAD_REQUEST)
50 | @ExceptionHandler(MissingServletRequestParameterException.class)
51 | public Response handleMissingServletRequestParameterException(MissingServletRequestParameterException e) {
52 | String msg = "缺少请求参数!";
53 | log.error(msg, e);
54 | return new Response().failure(msg);
55 | }
56 |
57 | /**
58 | * 400 - Bad Request
59 | */
60 | @ResponseStatus(HttpStatus.BAD_REQUEST)
61 | @ExceptionHandler(HttpMessageNotReadableException.class)
62 | public Response handleHttpMessageNotReadableException(HttpMessageNotReadableException e) {
63 | String msg = e.getMessage();
64 | log.error("参数解析失败:", e);
65 | return new Response().failure(msg);
66 | }
67 |
68 | /**
69 | * 400 - Bad Request
70 | */
71 | @ResponseStatus(HttpStatus.BAD_REQUEST)
72 | @ExceptionHandler(MethodArgumentNotValidException.class)
73 | public Response handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
74 | String msg = handleBindingResult(e.getBindingResult());
75 | log.error("方法参数无效: ", e);
76 | return new Response().failure(msg);
77 | }
78 |
79 | /**
80 | * 400 - Bad Request
81 | */
82 | @ResponseStatus(HttpStatus.BAD_REQUEST)
83 | @ExceptionHandler(BindException.class)
84 | public Response handleBindException(BindException e) {
85 | String msg = handleBindingResult(e.getBindingResult());
86 | log.error("参数绑定失败:", e);
87 | return new Response().failure(msg);
88 | }
89 |
90 | /**
91 | * 400 - Bad Request
92 | */
93 | @ResponseStatus(HttpStatus.BAD_REQUEST)
94 | @ExceptionHandler(ConstraintViolationException.class)
95 | public Response handleServiceException(ConstraintViolationException e) {
96 | Set> violations = e.getConstraintViolations();
97 | String msg = violations.iterator().next().getMessage();
98 | log.error("参数验证失败:", e);
99 | return new Response().failure(msg);
100 | }
101 |
102 | /**
103 | * 400 - Bad Request
104 | */
105 | @ResponseStatus(HttpStatus.BAD_REQUEST)
106 | @ExceptionHandler(ValidationException.class)
107 | public Response handleValidationException(ValidationException e) {
108 | String msg = e.getMessage();
109 | log.error("参数验证失败:", e);
110 | return new Response().failure(msg);
111 | }
112 |
113 | /**
114 | * 401 - Unauthorized
115 | */
116 | @ResponseStatus(HttpStatus.UNAUTHORIZED)
117 | @ExceptionHandler(LoginException.class)
118 | public Response handleLoginException(LoginException e) {
119 | String msg = e.getMessage();
120 | log.error("登录异常:", e);
121 | return new Response().failure(msg);
122 | }
123 |
124 | /**
125 | * 403 - Unauthorized
126 | */
127 | @ResponseStatus(HttpStatus.FORBIDDEN)
128 | @ExceptionHandler(UnauthorizedException.class)
129 | public Response handleLoginException(UnauthorizedException e) {
130 | String msg = e.getMessage();
131 | log.error("用户无权限:", e);
132 | return new Response().failure(HttpStatus.FORBIDDEN, "用户无权限!", null);
133 | }
134 |
135 | /**
136 | * 405 - Method Not Allowed
137 | */
138 | @ResponseStatus(HttpStatus.METHOD_NOT_ALLOWED)
139 | @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
140 | public Response handleHttpRequestMethodNotSupportedException(HttpRequestMethodNotSupportedException e) {
141 | String msg = "不支持当前请求方法!";
142 | log.error(msg, e);
143 | return new Response().failure(msg);
144 | }
145 |
146 | /**
147 | * 415 - Unsupported Media Type
148 | */
149 | @ResponseStatus(HttpStatus.UNSUPPORTED_MEDIA_TYPE)
150 | @ExceptionHandler(HttpMediaTypeNotSupportedException.class)
151 | public Response handleHttpMediaTypeNotSupportedException(Exception e) {
152 | String msg = "不支持当前媒体类型!";
153 | log.error(msg, e);
154 | return new Response().failure(msg);
155 | }
156 |
157 | /**
158 | * 422 - UNPROCESSABLE_ENTITY
159 | */
160 | @ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
161 | @ExceptionHandler(MaxUploadSizeExceededException.class)
162 | public Response handleMaxUploadSizeExceededException(Exception e) {
163 | String msg = "所上传文件大小超过最大限制,上传失败!";
164 | log.error(msg, e);
165 | return new Response().failure(msg);
166 | }
167 |
168 | /**
169 | * 500 - Internal Server Error
170 | */
171 | @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
172 | @ExceptionHandler(ServiceNotFoundException.class)
173 | public Response handleServiceException(ServiceNotFoundException e) {
174 | String msg = "服务内部异常:" + e.getMessage();
175 | log.error(msg, e);
176 | return new Response().failure(msg);
177 | }
178 |
179 | /**
180 | * 500 - Internal Server Error
181 | */
182 | @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
183 | @ExceptionHandler(Exception.class)
184 | public Response handleException(Exception e) {
185 | String msg = "服务内部异常!" + e.getMessage();
186 | log.error(msg, e);
187 | return new Response().failure(msg);
188 | }
189 |
190 | /**
191 | * 处理参数绑定异常,并拼接出错的参数异常信息。
192 | *
193 | * 创建人:leigq
194 | * 创建时间:2017年10月16日 下午9:09:22
195 | *
196 | * 修改人:
197 | * 修改时间:
198 | * 修改备注:
199 | *
200 | *
201 | * @param result
202 | */
203 | private String handleBindingResult(BindingResult result) {
204 | if (result.hasErrors()) {
205 | final List fieldErrors = result.getFieldErrors();
206 | return fieldErrors.iterator().next().getDefaultMessage();
207 | }
208 | return null;
209 | }
210 | }
211 |
--------------------------------------------------------------------------------
/src/main/java/com/leigq/www/shiro/web/exception/LoginException.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.web.exception;
2 |
3 | /**
4 | * @author :leigq
5 | * @date :2019/7/1 09:26
6 | * @description:登录异常
7 | */
8 | public class LoginException extends RuntimeException {
9 | public LoginException() {
10 | super();
11 | }
12 |
13 | public LoginException(String message) {
14 | super(message);
15 | }
16 |
17 | public LoginException(String message, Throwable cause) {
18 | super(message, cause);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | spring:
2 | profiles:
3 | active: dev
--------------------------------------------------------------------------------
/src/main/resources/config/application-dev.yml:
--------------------------------------------------------------------------------
1 | mybatis-plus:
2 | configuration:
3 | map-underscore-to-camel-case: true
4 | use-generated-keys: true
5 | mapper-locations: classpath*:/mappers/**/*.xml
6 | type-aliases-package: com.leigq.www.shiro.domain.entity
7 | server:
8 | tomcat:
9 | uri-encoding: UTF-8
10 | spring:
11 | datasource:
12 | connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000;config.decrypt=true;config.decrypt.key=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKPYsCl3alwZlRb1vKoFdVu0LP3Nm/+vH5iOWxI83pkUbrQc13Lxz/VT3D+H+ziaUpUsA+ZjG4iZGTDJWZnP8kcCAwEAAQ==
13 | driver-class-name: com.mysql.cj.jdbc.Driver
14 | filters: config,stat,wall,slf4j
15 | initialSize: 5
16 | maxActive: 20
17 | maxPoolPreparedStatementPerConnectionSize: 20
18 | maxWait: 60000
19 | minEvictableIdleTimeMillis: 300000
20 | minIdle: 5
21 | password: kGJF6c+pzVsf49LGs01ss0yijBGXIpNEp20cMkNCQo3ONaeMNPeoW9M89v+nGeiWs95/D2Ms59uGyydDGUWpmg==
22 | poolPreparedStatements: true
23 | testOnBorrow: false
24 | testOnReturn: false
25 | testWhileIdle: true
26 | timeBetweenEvictionRunsMillis: 60000
27 | type: com.alibaba.druid.pool.DruidDataSource
28 | url: jdbc:mysql://localhost:3306/shiro?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=true&serverTimezone=UTC
29 | username: root
30 | validationQuery: SELECT 1 FROM DUAL
31 | thymeleaf:
32 | cache: false
33 | redis:
34 | host: localhost
35 | port: 6379
36 | timeout: 2000s
37 | password: 111111
--------------------------------------------------------------------------------
/src/main/resources/config/application-prod.yml:
--------------------------------------------------------------------------------
1 | mybatis-plus:
2 | configuration:
3 | map-underscore-to-camel-case: true
4 | use-generated-keys: true
5 | mapper-locations: classpath*:/mappers/**/*.xml
6 | type-aliases-package: com.leigq.www.shiro.domain.entity
7 | server:
8 | tomcat:
9 | uri-encoding: UTF-8
10 | spring:
11 | datasource:
12 | connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000;config.decrypt=true;config.decrypt.key=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKPYsCl3alwZlRb1vKoFdVu0LP3Nm/+vH5iOWxI83pkUbrQc13Lxz/VT3D+H+ziaUpUsA+ZjG4iZGTDJWZnP8kcCAwEAAQ==
13 | driver-class-name: com.mysql.cj.jdbc.Driver
14 | filters: config,stat,wall,slf4j
15 | initialSize: 5
16 | maxActive: 20
17 | maxPoolPreparedStatementPerConnectionSize: 20
18 | maxWait: 60000
19 | minEvictableIdleTimeMillis: 300000
20 | minIdle: 5
21 | password: kGJF6c+pzVsf49LGs01ss0yijBGXIpNEp20cMkNCQo3ONaeMNPeoW9M89v+nGeiWs95/D2Ms59uGyydDGUWpmg==
22 | poolPreparedStatements: true
23 | testOnBorrow: false
24 | testOnReturn: false
25 | testWhileIdle: true
26 | timeBetweenEvictionRunsMillis: 60000
27 | type: com.alibaba.druid.pool.DruidDataSource
28 | url: jdbc:mysql://localhost:3306/shiro?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=true&serverTimezone=UTC
29 | username: root
30 | validationQuery: SELECT 1 FROM DUAL
31 | thymeleaf:
32 | cache: false
33 | redis:
34 | host: localhost
35 | port: 6379
36 | timeout: 2000s
37 | password: 111111
--------------------------------------------------------------------------------
/src/main/resources/config/application-test.yml:
--------------------------------------------------------------------------------
1 | mybatis-plus:
2 | configuration:
3 | map-underscore-to-camel-case: true
4 | use-generated-keys: true
5 | mapper-locations: classpath*:/mappers/**/*.xml
6 | type-aliases-package: com.leigq.www.shiro.domain.entity
7 | server:
8 | tomcat:
9 | uri-encoding: UTF-8
10 | spring:
11 | datasource:
12 | connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000;config.decrypt=true;config.decrypt.key=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKPYsCl3alwZlRb1vKoFdVu0LP3Nm/+vH5iOWxI83pkUbrQc13Lxz/VT3D+H+ziaUpUsA+ZjG4iZGTDJWZnP8kcCAwEAAQ==
13 | driver-class-name: com.mysql.cj.jdbc.Driver
14 | filters: config,stat,wall,slf4j
15 | initialSize: 5
16 | maxActive: 20
17 | maxPoolPreparedStatementPerConnectionSize: 20
18 | maxWait: 60000
19 | minEvictableIdleTimeMillis: 300000
20 | minIdle: 5
21 | password: kGJF6c+pzVsf49LGs01ss0yijBGXIpNEp20cMkNCQo3ONaeMNPeoW9M89v+nGeiWs95/D2Ms59uGyydDGUWpmg==
22 | poolPreparedStatements: true
23 | testOnBorrow: false
24 | testOnReturn: false
25 | testWhileIdle: true
26 | timeBetweenEvictionRunsMillis: 60000
27 | type: com.alibaba.druid.pool.DruidDataSource
28 | url: jdbc:mysql://localhost:3306/shiro?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=true&serverTimezone=UTC
29 | username: root
30 | validationQuery: SELECT 1 FROM DUAL
31 | thymeleaf:
32 | cache: false
33 | redis:
34 | host: localhost
35 | port: 6379
36 | timeout: 2000s
37 | password: 111111
--------------------------------------------------------------------------------
/src/main/resources/mappers/PermissionMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
16 |
17 |
--------------------------------------------------------------------------------
/src/main/resources/mappers/RoleMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
16 |
17 |
--------------------------------------------------------------------------------
/src/main/resources/mappers/RolePermissionMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/main/resources/mappers/UserMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/main/resources/mappers/UserRoleMapper.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/src/main/resources/sql/shiro-V1.0.0.sql:
--------------------------------------------------------------------------------
1 | /*
2 | SQLyog Ultimate v12.5.0 (64 bit)
3 | MySQL - 5.7.21-log : Database - shiro
4 | *********************************************************************
5 | */
6 |
7 | /*!40101 SET NAMES utf8 */;
8 |
9 | /*!40101 SET SQL_MODE=''*/;
10 |
11 | /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
12 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
13 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
14 | /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
15 | CREATE DATABASE /*!32312 IF NOT EXISTS*/`shiro` /*!40100 DEFAULT CHARACTER SET utf8 */;
16 |
17 | USE `shiro`;
18 |
19 | /*Table structure for table `sys_permission` */
20 |
21 | DROP TABLE IF EXISTS `sys_permission`;
22 |
23 | CREATE TABLE `sys_permission` (
24 | `permissionId` int(11) NOT NULL AUTO_INCREMENT,
25 | `available` bit(1) DEFAULT NULL,
26 | `parentId` bigint(20) DEFAULT NULL,
27 | `parentIds` varchar(255) DEFAULT NULL,
28 | `permission` varchar(255) DEFAULT NULL,
29 | `permissionName` varchar(255) NOT NULL,
30 | `resourceType` enum('menu','button') DEFAULT NULL,
31 | `url` varchar(255) DEFAULT NULL,
32 | PRIMARY KEY (`permissionId`)
33 | ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
34 |
35 | /*Data for the table `sys_permission` */
36 |
37 | insert into `sys_permission`(`permissionId`,`available`,`parentId`,`parentIds`,`permission`,`permissionName`,`resourceType`,`url`) values
38 | (1,'\0',0,'0/','user:view','用户管理','menu','user/userList'),
39 | (2,'\0',1,'0/1','user:add','用户添加','button','user/userAdd'),
40 | (3,'\0',1,'0/1','user:del','用户删除','button','user/userDel');
41 |
42 | /*Table structure for table `sys_role` */
43 |
44 | DROP TABLE IF EXISTS `sys_role`;
45 |
46 | CREATE TABLE `sys_role` (
47 | `roleId` int(11) NOT NULL AUTO_INCREMENT,
48 | `available` bit(1) DEFAULT NULL,
49 | `description` varchar(255) DEFAULT NULL,
50 | `role` varchar(255) NOT NULL,
51 | PRIMARY KEY (`roleId`),
52 | UNIQUE KEY `UK_8sggqkp1sv8guimk979mf6anf` (`role`)
53 | ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
54 |
55 | /*Data for the table `sys_role` */
56 |
57 | insert into `sys_role`(`roleId`,`available`,`description`,`role`) values
58 | (1,'\0','管理员','admin'),
59 | (2,'\0','VIP会员','vip'),
60 | (3,'','test','test');
61 |
62 | /*Table structure for table `sys_role_permission` */
63 |
64 | DROP TABLE IF EXISTS `sys_role_permission`;
65 |
66 | CREATE TABLE `sys_role_permission` (
67 | `permissionId` int(11) NOT NULL,
68 | `roleId` int(11) NOT NULL,
69 | KEY `FKpuhqkr403td1v28c3e71cgm4b` (`roleId`),
70 | KEY `FKjwye79px7p33gsqu4kftj0ua1` (`permissionId`),
71 | CONSTRAINT `FKjwye79px7p33gsqu4kftj0ua1` FOREIGN KEY (`permissionId`) REFERENCES `sys_permission` (`permissionId`),
72 | CONSTRAINT `FKpuhqkr403td1v28c3e71cgm4b` FOREIGN KEY (`roleId`) REFERENCES `sys_role` (`roleId`)
73 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
74 |
75 | /*Data for the table `sys_role_permission` */
76 |
77 | insert into `sys_role_permission`(`permissionId`,`roleId`) values
78 | (1,1),
79 | (2,1),
80 | (3,2);
81 |
82 | /*Table structure for table `sys_user` */
83 |
84 | DROP TABLE IF EXISTS `sys_user`;
85 |
86 | CREATE TABLE `sys_user` (
87 | `userId` int(11) NOT NULL AUTO_INCREMENT,
88 | `createTime` datetime DEFAULT NULL,
89 | `email` varchar(255) DEFAULT NULL,
90 | `expiredDate` date DEFAULT NULL,
91 | `name` varchar(255) NOT NULL,
92 | `password` varchar(255) NOT NULL,
93 | `salt` varchar(255) DEFAULT NULL,
94 | `state` tinyint(4) NOT NULL,
95 | `userName` varchar(255) NOT NULL,
96 | PRIMARY KEY (`userId`),
97 | UNIQUE KEY `UK_hl8fftx66p59oqgkkcfit3eay` (`userName`)
98 | ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
99 |
100 | /*Data for the table `sys_user` */
101 |
102 | insert into `sys_user`(`userId`,`createTime`,`email`,`expiredDate`,`name`,`password`,`salt`,`state`,`userName`) values
103 | (1,'2019-06-28 18:00:31',NULL,NULL,'管理员','d3c59d25033dbf980d29554025c23a75','8d78869f470951332959580424d4bf4f',0,'admin');
104 |
105 | /*Table structure for table `sys_user_role` */
106 |
107 | DROP TABLE IF EXISTS `sys_user_role`;
108 |
109 | CREATE TABLE `sys_user_role` (
110 | `userId` int(11) NOT NULL,
111 | `roleId` int(11) NOT NULL,
112 | KEY `FKgnn5rpnbwhx9fu93b19daiwbt` (`roleId`),
113 | KEY `FKsaymuhj4r4qr22w2q1e2oewx` (`userId`),
114 | CONSTRAINT `FKgnn5rpnbwhx9fu93b19daiwbt` FOREIGN KEY (`roleId`) REFERENCES `sys_role` (`roleId`),
115 | CONSTRAINT `FKsaymuhj4r4qr22w2q1e2oewx` FOREIGN KEY (`userId`) REFERENCES `sys_user` (`userId`)
116 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
117 |
118 | /*Data for the table `sys_user_role` */
119 |
120 | insert into `sys_user_role`(`userId`,`roleId`) values
121 | (1,1);
122 |
123 | /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
124 | /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
125 | /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
126 | /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
127 |
--------------------------------------------------------------------------------
/src/main/resources/sql/shiro-V1.0.1.sql:
--------------------------------------------------------------------------------
1 | /*
2 | SQLyog Ultimate v12.5.0 (64 bit)
3 | MySQL - 5.7.21-log : Database - shiro
4 | *********************************************************************
5 | */
6 |
7 | /*!40101 SET NAMES utf8 */;
8 |
9 | /*!40101 SET SQL_MODE=''*/;
10 |
11 | /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
12 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
13 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
14 | /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
15 | CREATE DATABASE /*!32312 IF NOT EXISTS*/`shiro` /*!40100 DEFAULT CHARACTER SET utf8 */;
16 |
17 | USE `shiro`;
18 |
19 | /*Table structure for table `sys_permission` */
20 |
21 | DROP TABLE IF EXISTS `sys_permission`;
22 |
23 | CREATE TABLE `sys_permission` (
24 | `permissionId` int(11) NOT NULL AUTO_INCREMENT,
25 | `available` bit(1) DEFAULT NULL,
26 | `parentId` bigint(20) DEFAULT NULL,
27 | `parentIds` varchar(255) DEFAULT NULL,
28 | `permission` varchar(255) DEFAULT NULL,
29 | `permissionName` varchar(255) NOT NULL,
30 | `resourceType` enum('menu','button') DEFAULT NULL,
31 | `url` varchar(255) DEFAULT NULL,
32 | PRIMARY KEY (`permissionId`)
33 | ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
34 |
35 | /*Data for the table `sys_permission` */
36 |
37 | insert into `sys_permission`(`permissionId`,`available`,`parentId`,`parentIds`,`permission`,`permissionName`,`resourceType`,`url`) values
38 | (1,'\0',0,'0/','user:view','用户管理','menu','user/userList'),
39 | (2,'\0',1,'0/1','user:add','用户添加','button','user/userAdd'),
40 | (3,'\0',1,'0/1','user:del','用户删除','button','user/userDel');
41 |
42 | /*Table structure for table `sys_role` */
43 |
44 | DROP TABLE IF EXISTS `sys_role`;
45 |
46 | CREATE TABLE `sys_role` (
47 | `roleId` int(11) NOT NULL AUTO_INCREMENT,
48 | `available` bit(1) DEFAULT NULL,
49 | `description` varchar(255) DEFAULT NULL,
50 | `role` varchar(255) NOT NULL,
51 | PRIMARY KEY (`roleId`),
52 | UNIQUE KEY `UK_8sggqkp1sv8guimk979mf6anf` (`role`)
53 | ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
54 |
55 | /*Data for the table `sys_role` */
56 |
57 | insert into `sys_role`(`roleId`,`available`,`description`,`role`) values
58 | (1,'\0','管理员','admin'),
59 | (2,'\0','VIP会员','vip'),
60 | (3,'','test','test');
61 |
62 | /*Table structure for table `sys_role_permission` */
63 |
64 | DROP TABLE IF EXISTS `sys_role_permission`;
65 |
66 | CREATE TABLE `sys_role_permission` (
67 | `id` bigint(20) NOT NULL AUTO_INCREMENT,
68 | `permissionId` int(11) NOT NULL,
69 | `roleId` int(11) NOT NULL,
70 | PRIMARY KEY (`id`),
71 | KEY `FKpuhqkr403td1v28c3e71cgm4b` (`roleId`),
72 | KEY `FKjwye79px7p33gsqu4kftj0ua1` (`permissionId`),
73 | CONSTRAINT `FKjwye79px7p33gsqu4kftj0ua1` FOREIGN KEY (`permissionId`) REFERENCES `sys_permission` (`permissionId`),
74 | CONSTRAINT `FKpuhqkr403td1v28c3e71cgm4b` FOREIGN KEY (`roleId`) REFERENCES `sys_role` (`roleId`)
75 | ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
76 |
77 | /*Data for the table `sys_role_permission` */
78 |
79 | insert into `sys_role_permission`(`id`,`permissionId`,`roleId`) values
80 | (1,1,1),
81 | (2,2,1);
82 |
83 | /*Table structure for table `sys_user` */
84 |
85 | DROP TABLE IF EXISTS `sys_user`;
86 |
87 | CREATE TABLE `sys_user` (
88 | `userId` int(11) NOT NULL AUTO_INCREMENT,
89 | `createTime` datetime DEFAULT NULL,
90 | `email` varchar(255) DEFAULT NULL,
91 | `expiredDate` date DEFAULT NULL,
92 | `name` varchar(255) NOT NULL,
93 | `password` varchar(255) NOT NULL,
94 | `salt` varchar(255) DEFAULT NULL,
95 | `state` tinyint(4) NOT NULL,
96 | `userName` varchar(255) NOT NULL,
97 | PRIMARY KEY (`userId`),
98 | UNIQUE KEY `UK_hl8fftx66p59oqgkkcfit3eay` (`userName`)
99 | ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
100 |
101 | /*Data for the table `sys_user` */
102 |
103 | insert into `sys_user`(`userId`,`createTime`,`email`,`expiredDate`,`name`,`password`,`salt`,`state`,`userName`) values
104 | (1,'2019-06-28 18:00:31',NULL,NULL,'管理员','d3c59d25033dbf980d29554025c23a75','8d78869f470951332959580424d4bf4f',0,'admin');
105 |
106 | /*Table structure for table `sys_user_role` */
107 |
108 | DROP TABLE IF EXISTS `sys_user_role`;
109 |
110 | CREATE TABLE `sys_user_role` (
111 | `id` bigint(20) NOT NULL AUTO_INCREMENT,
112 | `userId` int(11) NOT NULL,
113 | `roleId` int(11) NOT NULL,
114 | PRIMARY KEY (`id`),
115 | KEY `FKgnn5rpnbwhx9fu93b19daiwbt` (`roleId`),
116 | KEY `FKsaymuhj4r4qr22w2q1e2oewx` (`userId`),
117 | CONSTRAINT `FKgnn5rpnbwhx9fu93b19daiwbt` FOREIGN KEY (`roleId`) REFERENCES `sys_role` (`roleId`),
118 | CONSTRAINT `FKsaymuhj4r4qr22w2q1e2oewx` FOREIGN KEY (`userId`) REFERENCES `sys_user` (`userId`)
119 | ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
120 |
121 | /*Data for the table `sys_user_role` */
122 |
123 | insert into `sys_user_role`(`id`,`userId`,`roleId`) values
124 | (1,1,1);
125 |
126 | /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
127 | /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
128 | /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
129 | /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
130 |
--------------------------------------------------------------------------------
/src/test/java/com/leigq/www/shiro/base/BaseApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.base;
2 |
3 | import org.junit.After;
4 | import org.junit.Before;
5 | import org.junit.runner.RunWith;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 | import org.springframework.boot.test.context.SpringBootTest;
9 | import org.springframework.test.context.junit4.SpringRunner;
10 |
11 | @RunWith(SpringRunner.class)
12 | @SpringBootTest
13 | public abstract class BaseApplicationTests {
14 |
15 | protected Logger log = LoggerFactory.getLogger(this.getClass());
16 |
17 | private Long time;
18 |
19 | @Before
20 | public void setUp() {
21 | this.time = System.currentTimeMillis();
22 | log.info("==> 测试开始执行 <==");
23 | }
24 |
25 | @After
26 | public void tearDown() {
27 | log.info("==> 测试执行完成,耗时:{} ms <==", System.currentTimeMillis() - this.time);
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/test/java/com/leigq/www/shiro/test/ShiroApplicationTests.java:
--------------------------------------------------------------------------------
1 | package com.leigq.www.shiro.test;
2 |
3 | import com.leigq.www.shiro.base.BaseApplicationTests;
4 | import org.junit.Test;
5 | import org.springframework.beans.factory.annotation.Autowired;
6 | import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
7 |
8 | public class ShiroApplicationTests extends BaseApplicationTests {
9 |
10 | @Autowired
11 | private DataSourceProperties dataSourceProperties;
12 |
13 | @Test
14 | public void contextLoads() {
15 | // 测试时候可以正确获取 DataSourceProperties bean
16 | log.warn("DriverClassName is {}", dataSourceProperties.getDriverClassName());
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------