From d2694fbbfebf23cb025d261237a1c63c98faab5d Mon Sep 17 00:00:00 2001 From: cicadasmile <1327880701@qq.com> Date: Sun, 14 Jul 2019 23:34:12 +0800 Subject: [PATCH] =?UTF-8?q?SpringBoot2.0=20=E6=95=B4=E5=90=88=20Shiro=20?= =?UTF-8?q?=E6=A1=86=E6=9E=B6=EF=BC=8C=E5=AE=9E=E7=8E=B0=E7=94=A8=E6=88=B7?= =?UTF-8?q?=E6=9D=83=E9=99=90=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 +- pom.xml | 2 + ware-shiro-auth/pom.xml | 85 +++++++++++ .../java/com/boot/shiro/ShiroApplication.java | 11 ++ .../com/boot/shiro/config/DruidConfig.java | 136 ++++++++++++++++++ .../com/boot/shiro/config/ShiroConfig.java | 87 +++++++++++ .../com/boot/shiro/config/ShiroException.java | 20 +++ .../java/com/boot/shiro/config/UserRealm.java | 96 +++++++++++++ .../shiro/controller/ShiroController.java | 74 ++++++++++ .../com/boot/shiro/entity/SysMenuEntity.java | 133 +++++++++++++++++ .../com/boot/shiro/entity/SysUserEntity.java | 126 ++++++++++++++++ .../com/boot/shiro/mapper/SysMenuMapper.java | 24 ++++ .../com/boot/shiro/mapper/SysUserMapper.java | 25 ++++ .../java/com/boot/shiro/util/ShiroUtils.java | 63 ++++++++ .../src/main/resources/application.yml | 38 +++++ .../main/resources/mapper/SysMenuMapper.xml | 13 ++ .../main/resources/mapper/SysUserMapper.xml | 21 +++ ware-shiro-auth/src/main/resources/shiro.sql | 83 +++++++++++ 18 files changed, 1041 insertions(+), 1 deletion(-) create mode 100644 ware-shiro-auth/pom.xml create mode 100644 ware-shiro-auth/src/main/java/com/boot/shiro/ShiroApplication.java create mode 100644 ware-shiro-auth/src/main/java/com/boot/shiro/config/DruidConfig.java create mode 100644 ware-shiro-auth/src/main/java/com/boot/shiro/config/ShiroConfig.java create mode 100644 ware-shiro-auth/src/main/java/com/boot/shiro/config/ShiroException.java create mode 100644 ware-shiro-auth/src/main/java/com/boot/shiro/config/UserRealm.java create mode 100644 ware-shiro-auth/src/main/java/com/boot/shiro/controller/ShiroController.java create mode 100644 ware-shiro-auth/src/main/java/com/boot/shiro/entity/SysMenuEntity.java create mode 100644 ware-shiro-auth/src/main/java/com/boot/shiro/entity/SysUserEntity.java create mode 100644 ware-shiro-auth/src/main/java/com/boot/shiro/mapper/SysMenuMapper.java create mode 100644 ware-shiro-auth/src/main/java/com/boot/shiro/mapper/SysUserMapper.java create mode 100644 ware-shiro-auth/src/main/java/com/boot/shiro/util/ShiroUtils.java create mode 100644 ware-shiro-auth/src/main/resources/application.yml create mode 100644 ware-shiro-auth/src/main/resources/mapper/SysMenuMapper.xml create mode 100644 ware-shiro-auth/src/main/resources/mapper/SysUserMapper.xml create mode 100644 ware-shiro-auth/src/main/resources/shiro.sql 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 + 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='用户与角色对应关系';