diff --git a/README.md b/README.md
index d8d6e1e..45cc7f0 100644
--- a/README.md
+++ b/README.md
@@ -27,9 +27,12 @@
09、SpringBoot2.0 整合 JWT 框架,解决Token跨域验证问题
-
+
10、SpringBoot2.0 整合 FastDFS 中间件,实现文件分布管理
+
+11、SpringBoot2.0 整合 Shiro 框架,实现用户权限管理
+
持续更新中...
## 项目简介
diff --git a/pom.xml b/pom.xml
index 63329bc..1727ec4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -37,6 +37,8 @@
ware-jwt-token
ware-fast-dfs
+
+ ware-shiro-auth
diff --git a/ware-shiro-auth/pom.xml b/ware-shiro-auth/pom.xml
new file mode 100644
index 0000000..086b5eb
--- /dev/null
+++ b/ware-shiro-auth/pom.xml
@@ -0,0 +1,85 @@
+
+
+
+ org.springframework.boot
+ spring-boot-starters
+ 2.1.3.RELEASE
+
+ 4.0.0
+ com.shiro.auth
+ ware-shiro-auth
+ jar
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+ org.springframework.boot
+ spring-boot-starter-aop
+
+
+ org.springframework.boot
+ spring-boot-starter-test
+
+
+
+ org.apache.shiro
+ shiro-core
+ 1.4.0
+
+
+ org.apache.shiro
+ shiro-spring
+ 1.4.0
+
+
+ org.mybatis.spring.boot
+ mybatis-spring-boot-starter
+ 1.3.2
+
+
+ com.baomidou
+ mybatis-plus
+ 2.1.9
+
+
+ mysql
+ mysql-connector-java
+ 5.1.38
+
+
+ com.alibaba
+ druid-spring-boot-starter
+ 1.1.13
+
+
+ com.alibaba
+ druid
+ 1.1.10
+
+
+
+
+ ${project.artifactId}
+
+
+ src/main/resources
+ true
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 2.3.2
+
+
+ 1.8
+
+
+
+
+
\ No newline at end of file
diff --git a/ware-shiro-auth/src/main/java/com/boot/shiro/ShiroApplication.java b/ware-shiro-auth/src/main/java/com/boot/shiro/ShiroApplication.java
new file mode 100644
index 0000000..3b01d8a
--- /dev/null
+++ b/ware-shiro-auth/src/main/java/com/boot/shiro/ShiroApplication.java
@@ -0,0 +1,11 @@
+package com.boot.shiro;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+
+@SpringBootApplication
+public class ShiroApplication {
+ public static void main(String[] args) {
+ SpringApplication.run(ShiroApplication.class,args) ;
+ }
+}
diff --git a/ware-shiro-auth/src/main/java/com/boot/shiro/config/DruidConfig.java b/ware-shiro-auth/src/main/java/com/boot/shiro/config/DruidConfig.java
new file mode 100644
index 0000000..c59ccb7
--- /dev/null
+++ b/ware-shiro-auth/src/main/java/com/boot/shiro/config/DruidConfig.java
@@ -0,0 +1,136 @@
+package com.boot.shiro.config;
+
+import com.alibaba.druid.pool.DruidDataSource;
+import com.alibaba.druid.support.http.StatViewServlet;
+import com.alibaba.druid.support.http.WebStatFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.boot.web.servlet.ServletRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import javax.sql.DataSource;
+
+/**
+ * Druid数据库连接池配置文件
+ */
+@Configuration
+public class DruidConfig {
+ private static final Logger logger = LoggerFactory.getLogger(DruidConfig.class);
+
+ @Value("${spring.datasource.druid.url}")
+ private String dbUrl;
+
+ @Value("${spring.datasource.druid.username}")
+ private String username;
+
+ @Value("${spring.datasource.druid.password}")
+ private String password;
+
+ @Value("${spring.datasource.druid.driverClassName}")
+ private String driverClassName;
+
+ @Value("${spring.datasource.druid.initial-size}")
+ private int initialSize;
+
+ @Value("${spring.datasource.druid.max-active}")
+ private int maxActive;
+
+ @Value("${spring.datasource.druid.min-idle}")
+ private int minIdle;
+
+ @Value("${spring.datasource.druid.max-wait}")
+ private int maxWait;
+
+ @Value("${spring.datasource.druid.pool-prepared-statements}")
+ private boolean poolPreparedStatements;
+
+ @Value("${spring.datasource.druid.max-pool-prepared-statement-per-connection-size}")
+ private int maxPoolPreparedStatementPerConnectionSize;
+
+ @Value("${spring.datasource.druid.time-between-eviction-runs-millis}")
+ private int timeBetweenEvictionRunsMillis;
+
+ @Value("${spring.datasource.druid.min-evictable-idle-time-millis}")
+ private int minEvictableIdleTimeMillis;
+
+ @Value("${spring.datasource.druid.max-evictable-idle-time-millis}")
+ private int maxEvictableIdleTimeMillis;
+
+ @Value("${spring.datasource.druid.validation-query}")
+ private String validationQuery;
+
+ @Value("${spring.datasource.druid.test-while-idle}")
+ private boolean testWhileIdle;
+
+ @Value("${spring.datasource.druid.test-on-borrow}")
+ private boolean testOnBorrow;
+
+ @Value("${spring.datasource.druid.test-on-return}")
+ private boolean testOnReturn;
+
+ @Value("${spring.datasource.druid.filters}")
+ private String filters;
+
+ @Value("{spring.datasource.druid.connection-properties}")
+ private String connectionProperties;
+
+ @Bean //声明其为Bean实例
+ @Primary //在同样的DataSource中,首先使用被标注的DataSource
+ public DataSource dataSource() {
+ DruidDataSource datasource = new DruidDataSource();
+ datasource.setUrl(dbUrl);
+ datasource.setUsername(username);
+ datasource.setPassword(password);
+ datasource.setDriverClassName(driverClassName);
+ datasource.setInitialSize(initialSize);
+ datasource.setMinIdle(minIdle);
+ datasource.setMaxActive(maxActive);
+ datasource.setMaxWait(maxWait);
+ datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
+ datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
+ datasource.setMaxEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
+ datasource.setValidationQuery(validationQuery);
+ datasource.setTestWhileIdle(testWhileIdle);
+ datasource.setTestOnBorrow(testOnBorrow);
+ datasource.setTestOnReturn(testOnReturn);
+ datasource.setPoolPreparedStatements(poolPreparedStatements);
+ datasource.setMaxPoolPreparedStatementPerConnectionSize(maxPoolPreparedStatementPerConnectionSize);
+ try {
+ datasource.setFilters(filters);
+ } catch (Exception e) {
+ logger.error("druid configuration initialization filter", e);
+ }
+ datasource.setConnectionProperties(connectionProperties);
+ return datasource;
+ }
+ @Bean
+ public ServletRegistrationBean statViewServlet(){
+ ServletRegistrationBean srb =
+ new ServletRegistrationBean(new StatViewServlet(),"/druid/*");
+ // 设置ip白名单
+ // srb.addInitParameter("allow","127.0.0.1");
+ // 设置ip黑名单,优先级高于白名单
+ // srb.addInitParameter("deny","192.168.0.19");
+ //设置控制台管理用户
+ srb.addInitParameter("loginUsername","root");
+ srb.addInitParameter("loginPassword","root");
+ //是否可以重置数据
+ srb.addInitParameter("resetEnable","false");
+ return srb;
+ }
+ @Bean
+ public FilterRegistrationBean statFilter(){
+ //创建过滤器
+ FilterRegistrationBean frb =
+ new FilterRegistrationBean(new WebStatFilter());
+ //设置过滤器过滤路径
+ frb.addUrlPatterns("/*");
+ //忽略过滤的形式
+ frb.addInitParameter("exclusions",
+ "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*");
+ return frb;
+ }
+}
\ No newline at end of file
diff --git a/ware-shiro-auth/src/main/java/com/boot/shiro/config/ShiroConfig.java b/ware-shiro-auth/src/main/java/com/boot/shiro/config/ShiroConfig.java
new file mode 100644
index 0000000..0246ff6
--- /dev/null
+++ b/ware-shiro-auth/src/main/java/com/boot/shiro/config/ShiroConfig.java
@@ -0,0 +1,87 @@
+package com.boot.shiro.config;
+
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.session.mgt.SessionManager;
+import org.apache.shiro.spring.LifecycleBeanPostProcessor;
+import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
+import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
+import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
+import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
+import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * Shiro 配置文件
+ */
+@Configuration
+public class ShiroConfig {
+ /**
+ * Session Manager:会话管理
+ * 即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;
+ * 会话可以是普通JavaSE环境的,也可以是如Web环境的;
+ */
+ @Bean("sessionManager")
+ public SessionManager sessionManager(){
+ DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
+ //设置session过期时间
+ sessionManager.setGlobalSessionTimeout(60 * 60 * 1000);
+ sessionManager.setSessionValidationSchedulerEnabled(true);
+ // 去掉shiro登录时url里的JSESSIONID
+ sessionManager.setSessionIdUrlRewritingEnabled(false);
+ return sessionManager;
+ }
+
+ /**
+ * SecurityManager:安全管理器
+ */
+ @Bean("securityManager")
+ public SecurityManager securityManager(UserRealm userRealm, SessionManager sessionManager) {
+ DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
+ securityManager.setSessionManager(sessionManager);
+ securityManager.setRealm(userRealm);
+ return securityManager;
+ }
+ /**
+ * ShiroFilter是整个Shiro的入口点,用于拦截需要安全控制的请求进行处理
+ */
+ @Bean("shiroFilter")
+ public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
+ ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
+ shiroFilter.setSecurityManager(securityManager);
+ shiroFilter.setLoginUrl("/userLogin");
+ shiroFilter.setUnauthorizedUrl("/");
+ Map filterMap = new LinkedHashMap<>();
+ filterMap.put("/userLogin", "anon");
+ shiroFilter.setFilterChainDefinitionMap(filterMap);
+ return shiroFilter;
+ }
+ /**
+ * 管理Shiro中一些bean的生命周期
+ */
+ @Bean("lifecycleBeanPostProcessor")
+ public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
+ return new LifecycleBeanPostProcessor();
+ }
+ /**
+ * 扫描上下文,寻找所有的Advistor(通知器)
+ * 将这些Advisor应用到所有符合切入点的Bean中。
+ */
+ @Bean
+ public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
+ DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
+ proxyCreator.setProxyTargetClass(true);
+ return proxyCreator;
+ }
+ /**
+ * 匹配所有加了 Shiro 认证注解的方法
+ */
+ @Bean
+ public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
+ AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
+ advisor.setSecurityManager(securityManager);
+ return advisor;
+ }
+}
\ No newline at end of file
diff --git a/ware-shiro-auth/src/main/java/com/boot/shiro/config/ShiroException.java b/ware-shiro-auth/src/main/java/com/boot/shiro/config/ShiroException.java
new file mode 100644
index 0000000..3f6e5f1
--- /dev/null
+++ b/ware-shiro-auth/src/main/java/com/boot/shiro/config/ShiroException.java
@@ -0,0 +1,20 @@
+package com.boot.shiro.config;
+
+import org.apache.shiro.authz.AuthorizationException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+
+@RestControllerAdvice
+public class ShiroException {
+
+ @ExceptionHandler(AuthorizationException.class)
+ public String authorizationException (){
+ return "抱歉您没有权限访问该内容!";
+ }
+
+ @ExceptionHandler(Exception.class)
+ public String handleException(Exception e){
+ return "系统异常!";
+ }
+
+}
\ No newline at end of file
diff --git a/ware-shiro-auth/src/main/java/com/boot/shiro/config/UserRealm.java b/ware-shiro-auth/src/main/java/com/boot/shiro/config/UserRealm.java
new file mode 100644
index 0000000..237e9ca
--- /dev/null
+++ b/ware-shiro-auth/src/main/java/com/boot/shiro/config/UserRealm.java
@@ -0,0 +1,96 @@
+package com.boot.shiro.config;
+
+import com.boot.shiro.entity.SysMenuEntity;
+import com.boot.shiro.entity.SysUserEntity;
+import com.boot.shiro.mapper.SysMenuMapper;
+import com.boot.shiro.mapper.SysUserMapper;
+import com.boot.shiro.util.ShiroUtils;
+import org.apache.shiro.authc.*;
+import org.apache.shiro.authc.credential.CredentialsMatcher;
+import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
+import org.apache.shiro.authz.AuthorizationInfo;
+import org.apache.shiro.authz.SimpleAuthorizationInfo;
+import org.apache.shiro.realm.AuthorizingRealm;
+import org.apache.shiro.subject.PrincipalCollection;
+import org.apache.shiro.util.ByteSource;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import javax.annotation.Resource;
+import java.util.*;
+
+/**
+ * Shiro 认证实体
+ */
+@Component
+public class UserRealm extends AuthorizingRealm {
+
+ @Resource
+ private SysUserMapper sysUserMapper ;
+ @Resource
+ private SysMenuMapper sysMenuMapper ;
+
+ /**
+ * 授权(验证权限时调用)
+ * 获取用户权限集合
+ */
+ @Override
+ public AuthorizationInfo doGetAuthorizationInfo
+ (PrincipalCollection principals) {
+ SysUserEntity user = (SysUserEntity)principals.getPrimaryPrincipal();
+ if(user == null) {
+ throw new UnknownAccountException("账号不存在");
+ }
+ List permsList;
+ //默认用户拥有最高权限
+ List menuList = sysMenuMapper.selectList();
+ permsList = new ArrayList<>(menuList.size());
+ for(SysMenuEntity menu : menuList){
+ permsList.add(menu.getPerms());
+ }
+ //用户权限列表
+ Set permsSet = new HashSet<>();
+ for(String perms : permsList){
+ if(StringUtils.isEmpty(perms)){
+ continue;
+ }
+ permsSet.addAll(Arrays.asList(perms.trim().split(",")));
+ }
+ SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
+ info.setStringPermissions(permsSet);
+ return info;
+ }
+
+ /**
+ * 认证(登录时调用)
+ * 验证用户登录
+ */
+ @Override
+ protected AuthenticationInfo doGetAuthenticationInfo(
+ AuthenticationToken authToken) throws AuthenticationException {
+ UsernamePasswordToken token = (UsernamePasswordToken)authToken;
+ //查询用户信息
+ SysUserEntity user = sysUserMapper.selectOne(token.getUsername());
+ //账号不存在
+ if(user == null) {
+ throw new UnknownAccountException("账号或密码不正确");
+ }
+ //账号锁定
+ if(user.getStatus() == 0){
+ throw new LockedAccountException("账号已被锁定,请联系管理员");
+ }
+ SimpleAuthenticationInfo info = new SimpleAuthenticationInfo
+ (user, user.getPassword(),
+ ByteSource.Util.bytes(user.getSalt()),
+ getName());
+ return info;
+ }
+
+ @Override
+ public void setCredentialsMatcher(CredentialsMatcher credentialsMatcher) {
+ HashedCredentialsMatcher shaCredentialsMatcher = new HashedCredentialsMatcher();
+ shaCredentialsMatcher.setHashAlgorithmName(ShiroUtils.hashAlgorithmName);
+ shaCredentialsMatcher.setHashIterations(ShiroUtils.hashIterations);
+ super.setCredentialsMatcher(shaCredentialsMatcher);
+ }
+}
\ No newline at end of file
diff --git a/ware-shiro-auth/src/main/java/com/boot/shiro/controller/ShiroController.java b/ware-shiro-auth/src/main/java/com/boot/shiro/controller/ShiroController.java
new file mode 100644
index 0000000..9b8b92a
--- /dev/null
+++ b/ware-shiro-auth/src/main/java/com/boot/shiro/controller/ShiroController.java
@@ -0,0 +1,74 @@
+package com.boot.shiro.controller;
+
+import com.boot.shiro.config.UserRealm;
+import com.boot.shiro.mapper.SysMenuMapper;
+import com.boot.shiro.util.ShiroUtils;
+import org.apache.shiro.authc.*;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.apache.shiro.subject.PrincipalCollection;
+import org.apache.shiro.subject.Subject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * Shrio 测试方法控制层
+ */
+@RestController
+public class ShiroController {
+ private static Logger LOGGER = LoggerFactory.getLogger(ShiroController.class) ;
+
+ @Resource
+ private SysMenuMapper sysMenuMapper ;
+ /**
+ * 登录测试
+ * http://localhost:7011/userLogin?userName=admin&passWord=admin
+ */
+ @RequestMapping("/userLogin")
+ public void userLogin (
+ @RequestParam(value = "userName") String userName,
+ @RequestParam(value = "passWord") String passWord){
+ try{
+ Subject subject = ShiroUtils.getSubject();
+ UsernamePasswordToken token = new UsernamePasswordToken(userName, passWord);
+ subject.login(token);
+ LOGGER.info("登录成功");
+ }catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 服务器每次重启请求该接口之前必须先请求上面登录接口
+ * http://localhost:7011/menu/list 获取所有菜单列表
+ * 权限要求:sys:user:shiro
+ */
+ @RequestMapping("/menu/list")
+ @RequiresPermissions("sys:user:shiro")
+ public List list(){
+ return sysMenuMapper.selectList() ;
+ }
+
+ /**
+ * 用户没有该权限,无法访问
+ * 权限要求:ccc:ddd:bbb
+ */
+ @RequestMapping("/menu/list2")
+ @RequiresPermissions("ccc:ddd:bbb")
+ public List list2(){
+ return sysMenuMapper.selectList() ;
+ }
+
+ /**
+ * 退出测试
+ */
+ @RequestMapping("/userLogOut")
+ public String logout (){
+ ShiroUtils.logout();
+ return "success" ;
+ }
+}
\ No newline at end of file
diff --git a/ware-shiro-auth/src/main/java/com/boot/shiro/entity/SysMenuEntity.java b/ware-shiro-auth/src/main/java/com/boot/shiro/entity/SysMenuEntity.java
new file mode 100644
index 0000000..31734cf
--- /dev/null
+++ b/ware-shiro-auth/src/main/java/com/boot/shiro/entity/SysMenuEntity.java
@@ -0,0 +1,133 @@
+package com.boot.shiro.entity;
+
+import com.baomidou.mybatisplus.annotations.TableField;
+import com.baomidou.mybatisplus.annotations.TableId;
+import com.baomidou.mybatisplus.annotations.TableName;
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 菜单管理
+ */
+@TableName("sys_menu")
+public class SysMenuEntity implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @TableId
+ private Long menuId;
+
+ private Long parentId;
+
+ @TableField(exist=false)
+ private String parentName;
+
+ private String name;
+
+ private String url;
+
+ private String perms;
+
+ private Integer type;
+
+ private String icon;
+
+ private Integer orderNum;
+
+ @TableField(exist=false)
+ private Boolean open;
+
+ @TableField(exist=false)
+ private List> list;
+
+ public static long getSerialVersionUID() {
+ return serialVersionUID;
+ }
+
+ public Long getMenuId() {
+ return menuId;
+ }
+
+ public void setMenuId(Long menuId) {
+ this.menuId = menuId;
+ }
+
+ public Long getParentId() {
+ return parentId;
+ }
+
+ public void setParentId(Long parentId) {
+ this.parentId = parentId;
+ }
+
+ public String getParentName() {
+ return parentName;
+ }
+
+ public void setParentName(String parentName) {
+ this.parentName = parentName;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public String getPerms() {
+ return perms;
+ }
+
+ public void setPerms(String perms) {
+ this.perms = perms;
+ }
+
+ public Integer getType() {
+ return type;
+ }
+
+ public void setType(Integer type) {
+ this.type = type;
+ }
+
+ public String getIcon() {
+ return icon;
+ }
+
+ public void setIcon(String icon) {
+ this.icon = icon;
+ }
+
+ public Integer getOrderNum() {
+ return orderNum;
+ }
+
+ public void setOrderNum(Integer orderNum) {
+ this.orderNum = orderNum;
+ }
+
+ public Boolean getOpen() {
+ return open;
+ }
+
+ public void setOpen(Boolean open) {
+ this.open = open;
+ }
+
+ public List> getList() {
+ return list;
+ }
+
+ public void setList(List> list) {
+ this.list = list;
+ }
+}
\ No newline at end of file
diff --git a/ware-shiro-auth/src/main/java/com/boot/shiro/entity/SysUserEntity.java b/ware-shiro-auth/src/main/java/com/boot/shiro/entity/SysUserEntity.java
new file mode 100644
index 0000000..5e2c5d4
--- /dev/null
+++ b/ware-shiro-auth/src/main/java/com/boot/shiro/entity/SysUserEntity.java
@@ -0,0 +1,126 @@
+package com.boot.shiro.entity;
+
+import com.baomidou.mybatisplus.annotations.TableField;
+import com.baomidou.mybatisplus.annotations.TableId;
+import com.baomidou.mybatisplus.annotations.TableName;
+import java.io.Serializable;
+import java.util.Date;
+import java.util.List;
+
+@TableName("sys_user")
+public class SysUserEntity implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ @TableId
+ private Long userId;
+
+ private String username;
+
+ private String password;
+
+ private String salt;
+
+ private String email;
+
+ private String mobile;
+
+ private Integer status;
+
+ @TableField(exist=false)
+ private List roleIdList;
+
+ private Date createTime;
+
+ private Long deptId;
+
+ @TableField(exist=false)
+ private String deptName;
+
+ public void setUserId(Long userId) {
+ this.userId = userId;
+ }
+
+ public Long getUserId() {
+ return userId;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setEmail(String email) {
+ this.email = email;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public void setMobile(String mobile) {
+ this.mobile = mobile;
+ }
+
+ public String getMobile() {
+ return mobile;
+ }
+
+ public void setStatus(Integer status) {
+ this.status = status;
+ }
+
+ public Integer getStatus() {
+ return status;
+ }
+
+ public void setCreateTime(Date createTime) {
+ this.createTime = createTime;
+ }
+
+ public Date getCreateTime() {
+ return createTime;
+ }
+
+ public List getRoleIdList() {
+ return roleIdList;
+ }
+
+ public void setRoleIdList(List roleIdList) {
+ this.roleIdList = roleIdList;
+ }
+
+ public String getSalt() {
+ return salt;
+ }
+
+ public void setSalt(String salt) {
+ this.salt = salt;
+ }
+
+ public Long getDeptId() {
+ return deptId;
+ }
+
+ public void setDeptId(Long deptId) {
+ this.deptId = deptId;
+ }
+
+ public String getDeptName() {
+ return deptName;
+ }
+
+ public void setDeptName(String deptName) {
+ this.deptName = deptName;
+ }
+}
\ No newline at end of file
diff --git a/ware-shiro-auth/src/main/java/com/boot/shiro/mapper/SysMenuMapper.java b/ware-shiro-auth/src/main/java/com/boot/shiro/mapper/SysMenuMapper.java
new file mode 100644
index 0000000..6b9305f
--- /dev/null
+++ b/ware-shiro-auth/src/main/java/com/boot/shiro/mapper/SysMenuMapper.java
@@ -0,0 +1,24 @@
+package com.boot.shiro.mapper;
+
+import com.boot.shiro.entity.SysMenuEntity;
+import org.apache.ibatis.annotations.Mapper;
+import java.util.List;
+
+@Mapper
+public interface SysMenuMapper {
+ /**
+ * 根据父菜单,查询子菜单
+ * @param parentId 父菜单ID
+ */
+ List queryListParentId(Long parentId);
+
+ /**
+ * 查询全部数据
+ */
+ List selectList () ;
+
+ /**
+ * 获取不包含按钮的菜单列表
+ */
+ List queryNotButtonList();
+}
\ No newline at end of file
diff --git a/ware-shiro-auth/src/main/java/com/boot/shiro/mapper/SysUserMapper.java b/ware-shiro-auth/src/main/java/com/boot/shiro/mapper/SysUserMapper.java
new file mode 100644
index 0000000..9dcdd2b
--- /dev/null
+++ b/ware-shiro-auth/src/main/java/com/boot/shiro/mapper/SysUserMapper.java
@@ -0,0 +1,25 @@
+package com.boot.shiro.mapper;
+
+import com.boot.shiro.entity.SysUserEntity;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import java.util.List;
+
+@Mapper
+public interface SysUserMapper {
+ /**
+ * 查询用户的所有权限
+ * @param userId 用户ID
+ */
+ List queryAllPerms(Long userId);
+
+ /**
+ * 根据用户名查询用户
+ */
+ SysUserEntity selectOne (@Param("userName") String userName) ;
+
+ /**
+ * 查询用户的所有菜单ID
+ */
+ List queryAllMenuId(Long userId);
+}
\ No newline at end of file
diff --git a/ware-shiro-auth/src/main/java/com/boot/shiro/util/ShiroUtils.java b/ware-shiro-auth/src/main/java/com/boot/shiro/util/ShiroUtils.java
new file mode 100644
index 0000000..e06ac2d
--- /dev/null
+++ b/ware-shiro-auth/src/main/java/com/boot/shiro/util/ShiroUtils.java
@@ -0,0 +1,63 @@
+package com.boot.shiro.util;
+import com.boot.shiro.entity.SysUserEntity;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.crypto.hash.SimpleHash;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.subject.Subject;
+/**
+ * Shiro工具类
+ */
+public class ShiroUtils {
+ /** 加密算法 */
+ public final static String hashAlgorithmName = "SHA-256";
+ /** 循环次数 */
+ public final static int hashIterations = 16;
+
+ public static String sha256(String password, String salt) {
+ return new SimpleHash(hashAlgorithmName, password, salt, hashIterations).toString();
+ }
+
+ // 获取一个测试账号 admin
+ public static void main(String[] args) {
+ // 3743a4c09a17e6f2829febd09ca54e627810001cf255ddcae9dabd288a949c4a
+ System.out.println(sha256("admin","123")) ;
+ }
+
+ /**
+ * 获取会话
+ */
+ public static Session getSession() {
+ return SecurityUtils.getSubject().getSession();
+ }
+
+ /**
+ * Subject:主体,代表了当前“用户”
+ */
+ public static Subject getSubject() {
+ return SecurityUtils.getSubject();
+ }
+
+ public static SysUserEntity getUserEntity() {
+ return (SysUserEntity)SecurityUtils.getSubject().getPrincipal();
+ }
+
+ public static Long getUserId() {
+ return getUserEntity().getUserId();
+ }
+
+ public static void setSessionAttribute(Object key, Object value) {
+ getSession().setAttribute(key, value);
+ }
+
+ public static Object getSessionAttribute(Object key) {
+ return getSession().getAttribute(key);
+ }
+
+ public static boolean isLogin() {
+ return SecurityUtils.getSubject().getPrincipal() != null;
+ }
+
+ public static void logout() {
+ SecurityUtils.getSubject().logout();
+ }
+}
\ No newline at end of file
diff --git a/ware-shiro-auth/src/main/resources/application.yml b/ware-shiro-auth/src/main/resources/application.yml
new file mode 100644
index 0000000..b0d79df
--- /dev/null
+++ b/ware-shiro-auth/src/main/resources/application.yml
@@ -0,0 +1,38 @@
+server:
+ port: 7011
+spring:
+ application:
+ name: ware-shiro-auth
+ main:
+ allow-bean-definition-overriding: true #当遇到同样名字的时候,是否允许覆盖注册
+ datasource:
+ type: com.alibaba.druid.pool.DruidDataSource
+ druid:
+ driverClassName: com.mysql.jdbc.Driver
+ url: jdbc:mysql://localhost:3306/spring-boot2?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8
+ username: root
+ password: root
+ initial-size: 10
+ max-active: 100
+ min-idle: 10
+ max-wait: 60000
+ pool-prepared-statements: true
+ max-pool-prepared-statement-per-connection-size: 20
+ time-between-eviction-runs-millis: 60000
+ min-evictable-idle-time-millis: 300000
+ max-evictable-idle-time-millis: 60000
+ validation-query: SELECT 1 FROM DUAL
+ # validation-query-timeout: 5000
+ test-on-borrow: false
+ test-on-return: false
+ test-while-idle: true
+ connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
+ #filters: #配置多个英文逗号分隔(统计,sql注入,log4j过滤)
+ filters: stat,wall
+ stat-view-servlet:
+ enabled: true
+ url-pattern: /druid/*
+# mybatis 配置
+mybatis:
+ type-aliases-package: com.boot.shiro.entity # 所有Entity别名类所在包
+ mapper-locations: classpath:mapper/*.xml # mapper映射文件
\ No newline at end of file
diff --git a/ware-shiro-auth/src/main/resources/mapper/SysMenuMapper.xml b/ware-shiro-auth/src/main/resources/mapper/SysMenuMapper.xml
new file mode 100644
index 0000000..95a3d9b
--- /dev/null
+++ b/ware-shiro-auth/src/main/resources/mapper/SysMenuMapper.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ware-shiro-auth/src/main/resources/mapper/SysUserMapper.xml b/ware-shiro-auth/src/main/resources/mapper/SysUserMapper.xml
new file mode 100644
index 0000000..579b47e
--- /dev/null
+++ b/ware-shiro-auth/src/main/resources/mapper/SysUserMapper.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ware-shiro-auth/src/main/resources/shiro.sql b/ware-shiro-auth/src/main/resources/shiro.sql
new file mode 100644
index 0000000..3778b9c
--- /dev/null
+++ b/ware-shiro-auth/src/main/resources/shiro.sql
@@ -0,0 +1,83 @@
+DROP TABLE IF EXISTS `sys_menu`;
+CREATE TABLE `sys_menu` (
+ `menu_id` bigint(20) NOT NULL AUTO_INCREMENT,
+ `parent_id` bigint(20) DEFAULT NULL COMMENT '父菜单ID,一级菜单为0',
+ `name` varchar(50) DEFAULT NULL COMMENT '菜单名称',
+ `url` varchar(200) DEFAULT NULL COMMENT '菜单URL',
+ `perms` varchar(500) DEFAULT NULL COMMENT '授权(多个用逗号分隔,如:user:list,user:create)',
+ `type` int(11) DEFAULT NULL COMMENT '类型 0:目录 1:菜单 2:按钮',
+ `icon` varchar(50) DEFAULT NULL COMMENT '菜单图标',
+ `order_num` int(11) DEFAULT NULL COMMENT '排序',
+ PRIMARY KEY (`menu_id`)
+) ENGINE=InnoDB AUTO_INCREMENT=31 DEFAULT CHARSET=utf8 COMMENT='菜单管理';
+
+-- ----------------------------
+-- Records of sys_menu
+-- ----------------------------
+INSERT INTO `sys_menu` VALUES ('1', '0', '权限菜单', 'menu/list', 'sys:user:shiro', '0', 'system', '0');
+
+-- ----------------------------
+-- Table structure for sys_role
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_role`;
+CREATE TABLE `sys_role` (
+ `role_id` bigint(20) NOT NULL AUTO_INCREMENT,
+ `role_name` varchar(100) DEFAULT NULL COMMENT '角色名称',
+ `remark` varchar(100) DEFAULT NULL COMMENT '备注',
+ `create_user_id` bigint(20) DEFAULT NULL COMMENT '创建者ID',
+ `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+ PRIMARY KEY (`role_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='角色';
+
+-- ----------------------------
+-- Records of sys_role
+-- ----------------------------
+
+-- ----------------------------
+-- Table structure for sys_role_menu
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_role_menu`;
+CREATE TABLE `sys_role_menu` (
+ `id` bigint(20) NOT NULL AUTO_INCREMENT,
+ `role_id` bigint(20) DEFAULT NULL COMMENT '角色ID',
+ `menu_id` bigint(20) DEFAULT NULL COMMENT '菜单ID',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='角色与菜单对应关系';
+
+-- ----------------------------
+-- Records of sys_role_menu
+-- ----------------------------
+
+-- ----------------------------
+-- Table structure for sys_user
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_user`;
+CREATE TABLE `sys_user` (
+ `user_id` bigint(20) NOT NULL AUTO_INCREMENT,
+ `username` varchar(50) NOT NULL COMMENT '用户名',
+ `password` varchar(100) DEFAULT NULL COMMENT '密码',
+ `salt` varchar(20) DEFAULT NULL COMMENT '盐',
+ `email` varchar(100) DEFAULT NULL COMMENT '邮箱',
+ `mobile` varchar(100) DEFAULT NULL COMMENT '手机号',
+ `status` tinyint(4) DEFAULT NULL COMMENT '状态 0:禁用 1:正常',
+ `create_user_id` bigint(20) DEFAULT NULL COMMENT '创建者ID',
+ `create_time` datetime DEFAULT NULL COMMENT '创建时间',
+ PRIMARY KEY (`user_id`),
+ UNIQUE KEY `username` (`username`)
+) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COMMENT='系统用户';
+
+-- ----------------------------
+-- Records of sys_user
+-- ----------------------------
+INSERT INTO `sys_user` VALUES ('1', 'admin', '3743a4c09a17e6f2829febd09ca54e627810001cf255ddcae9dabd288a949c4a', '123', 'cicada@163.com', '18967835678', '1', '1', '2019-01-18 11:11:11');
+
+-- ----------------------------
+-- Table structure for sys_user_role
+-- ----------------------------
+DROP TABLE IF EXISTS `sys_user_role`;
+CREATE TABLE `sys_user_role` (
+ `id` bigint(20) NOT NULL AUTO_INCREMENT,
+ `user_id` bigint(20) DEFAULT NULL COMMENT '用户ID',
+ `role_id` bigint(20) DEFAULT NULL COMMENT '角色ID',
+ PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户与角色对应关系';