前言:首先说明,这个需求很少(奇)见(葩)(由一个不懂代码的产品经理提出),要求公司内部后台系统里面,既能按照部门职能控制访问权限,又要能随意给某个人赋予权限。
二话不说,上配置。
1.数据库配置
数据库表为6个分别是: 用户表、角色表、权限表、用户角色中间表、角色权限中间表,用户权限中间表(实现对单独用户控制权限的关键)![](https://img-blog.csdnimg.cn/20191025165000819.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDgyODgwOA==,size_16,color_FFFFFF,t_70)
2.引入依赖
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
<mybatis.version>3.4.5</mybatis.version>
<commons-lang3.version>3.6</commons-lang3.version>
<mybatis-spring-boot.version>1.3.1</mybatis-spring-boot.version>
<fastjson.version>1.2.30</fastjson.version>
<druid.version>1.1.6</druid.version>
<shiro.version>1.4.0</shiro.version>
<lombok.version>1.16.18</lombok.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<!--<dependency>-->
<!--<groupId>org.springframework.boot</groupId>-->
<!--<artifactId>spring-boot-starter-security</artifactId>-->
<!--</dependency>-->
<!--<dependency>-->
<!--<groupId>org.springframework.security</groupId>-->
<!--<artifactId>spring-security-test</artifactId>-->
<!--<scope>test</scope>-->
<!--</dependency>-->
<!--消息中间件-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<!-- <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>${mybatis-spring-boot.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>com.vaadin.external.google</groupId>
<artifactId>android-json</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>${fastjson.version}</version>
</dependency>
<!-- cxf支持 -->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5</version>
<exclusions>
<exclusion>
<artifactId>commons-codec</artifactId>
<groupId>commons-codec</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.2.4</version>
<exclusions>
<exclusion>
<artifactId>mybatis-spring-boot-starter</artifactId>
<groupId>org.mybatis.spring.boot</groupId>
</exclusion>
</exclusions>
</dependency>
<!--阿里云OSS-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>2.8.3</version>
<exclusions>
<exclusion>
<artifactId>httpclient</artifactId>
<groupId>org.apache.httpcomponents</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
<version>1.1.0</version>
</dependency>
<!--阿里云核心-->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.4.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<!--极光推送-->
<dependency>
<groupId>cn.jpush.api</groupId>
<artifactId>jiguang-common</artifactId>
<version>1.1.4</version>
</dependency>
<dependency>
<groupId>cn.jpush.api</groupId>
<artifactId>jpush-client</artifactId>
<version>3.3.10</version>
<exclusions>
<exclusion>
<artifactId>jiguang-common</artifactId>
<groupId>cn.jpush.api</groupId>
</exclusion>
<exclusion>
<artifactId>httpclient</artifactId>
<groupId>org.apache.httpcomponents</groupId>
</exclusion>
</exclusions>
</dependency>
<!--压缩-->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.8</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>javase</artifactId>
<version>3.0.0</version>
</dependency>
<!-- HSSF需要引入的 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>RELEASE</version>
<exclusions>
<exclusion>
<artifactId>commons-codec</artifactId>
<groupId>commons-codec</groupId>
</exclusion>
</exclusions>
</dependency>
<!-- XSSF需要引入的 -->
<dependency>
<groupId>org.apache.xmlbeans</groupId>
<artifactId>xmlbeans</artifactId>
<version>2.6.0</version>
</dependency>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version><!--$NO-MVN-MAN-VER$ -->
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.9</version>
<exclusions>
<exclusion>
<artifactId>commons-codec</artifactId>
<groupId>commons-codec</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.9</version>
<exclusions>
<exclusion>
<artifactId>xmlbeans</artifactId>
<groupId>org.apache.xmlbeans</groupId>
</exclusion>
</exclusions>
</dependency>
<!--8.添加json数据处理的依赖 jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
<!--shiro的依赖-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.3.2</version>
<exclusions>
<exclusion>
<artifactId>shiro-core</artifactId>
<groupId>org.apache.shiro</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro.version}</version>
</dependency>
<!-- shiro+redis缓存插件 -->
<dependency>
<groupId>org.crazycake</groupId>
<artifactId>shiro-redis</artifactId>
<version>3.1.0</version>
<exclusions>
<exclusion>
<artifactId>shiro-core</artifactId>
<groupId>org.apache.shiro</groupId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>com.vdurmont</groupId>
<artifactId>emoji-java</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>org.yeauty</groupId>
<artifactId>netty-websocket-spring-boot-starter</artifactId>
<version>0.8.0</version>
</dependency>
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.56</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-solr</artifactId>
</dependency>
</dependencies>
3.yml文件的配置(其他配置不再赘述)
# 配置redis
redis:
host: 172.18.1.166
port: 6379
timeout: 6000ms
4.配置shirofilter
package com.longjie.yunxin.common.configuration;
import com.longjie.yunxin.common.util.MyCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
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.servlet.SimpleCookie;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.bind.annotation.CrossOrigin;
import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
@Configuration
@CrossOrigin
public class ShiroConfiguration {
/**
* 注入配置文件属性
*/
@Value("${spring.redis.host}")
private String host;//地址
@Value("${spring.redis.port}")
private int port;
@Value("${spring.redis.timeout}")
private String timeout;//过期时间
//将自己的验证方式加入容器
@Bean
public ShiroRealm ShiroRealm() {
ShiroRealm myShiroRealm = new ShiroRealm();
myShiroRealm.setCredentialsMatcher(credentialsMatcher());
return myShiroRealm;
}
@Bean
public MyCredentialsMatcher credentialsMatcher() {
return new MyCredentialsMatcher();
}
//Filter工厂,设置对应的过滤条件和跳转条件
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
// 自定义拦截器的配置
Map<String, Filter> filter = new HashMap<>();
filter.put("authc", new ShiroUserFilter());
shiroFilterFactoryBean.setFilters(filter);
// 没有登陆的用户只能访问登陆页面,前后端分离中登录界面跳转应由前端路由控制,后台仅返回json数据
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
// 静态资源
filterChainDefinitionMap.put("/shiro/**", "authc");
filterChainDefinitionMap.put("/Iuser/**", "authc");
filterChainDefinitionMap.put("/Imerchant/**", "authc");
filterChainDefinitionMap.put("/poi/**", "anon");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
//权限管理,配置主要是Realm的管理认证
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(ShiroRealm());
// 自定义缓存实现 使用redis
securityManager.setCacheManager(cacheManager());
// 自定义session管理 使用redis
securityManager.setSessionManager(sessionManager());
return securityManager;
}
/**
* cacheManager 缓存 redis实现
* 使用的是shiro-redis开源插件
*
* @return
*/
public RedisCacheManager cacheManager() {
RedisCacheManager redisCacheManager = new RedisCacheManager();
redisCacheManager.setRedisManager(redisManager());
redisCacheManager.setKeyPrefix("SPRINGBOOT_CACHE:"); //设置前缀
return redisCacheManager;
}
/**
* Session Manager
* 使用的是shiro-redis开源插件
*/
@Bean
public SessionManager sessionManager() {
SimpleCookie simpleCookie = new SimpleCookie("token");
simpleCookie.setPath("/");
simpleCookie.setHttpOnly(false);
SessionManager sessionManager = new SessionManager();
sessionManager.setSessionDAO(redisSessionDAO());
sessionManager.setSessionIdCookieEnabled(false);
sessionManager.setSessionIdUrlRewritingEnabled(false);
sessionManager.setDeleteInvalidSessions(true);
sessionManager.setSessionIdCookie(simpleCookie);
sessionManager.setGlobalSessionTimeout(1800 * 1000);//单位毫秒
return sessionManager;
}
/**
* 配置shiro redisManager
* 使用的是shiro-redis开源插件
*
* @return
*/
public RedisManager redisManager() {
RedisManager redisManager = new RedisManager();
redisManager.setHost(host);
redisManager.setPort(port);
redisManager.setTimeout(Integer.parseInt(timeout.replace("ms","")));
// redisManager.setPassword(password);
return redisManager;
}
/**
* RedisSessionDAO shiro sessionDao层的实现 通过redis
* 使用的是shiro-redis开源插件
*/
@Bean
public RedisSessionDAO redisSessionDAO() {
RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
redisSessionDAO.setRedisManager(redisManager());
redisSessionDAO.setKeyPrefix("SPRINGBOOT_SESSION:");
redisSessionDAO.setExpire(1800);//设置过期时间,单位s
return redisSessionDAO;
}
/***
* 授权所用配置
*
* @return
*/
@Bean
public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
return defaultAdvisorAutoProxyCreator;
}
//加入注解的使用,不加入这个注解不生效
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
/**
* Shiro生命周期处理器
* 此方法需要用static作为修饰词,否则无法通过@Value()注解的方式获取配置文件的值
*
*/
@Bean
public static LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
}
5.配置shiroRealm
package com.longjie.yunxin.common.configuration;
import com.longjie.yunxin.pojo.Manager;
import com.longjie.yunxin.pojo.Resource;
import com.longjie.yunxin.service.Shiro.ShiroService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Collection;
import java.util.List;
public class ShiroRealm extends AuthorizingRealm {
@Autowired
private ShiroService shiroService;
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
// 从数据库获取对应用户名密码的用户
Manager manager = shiroService.selectManagerByPhone(token.getUsername());
getAuthorizationCache().clear();//清除当前用户的权限信息缓存
if (manager != null) {
//单用户登录
//处理session
DefaultWebSecurityManager securityManager = (DefaultWebSecurityManager) SecurityUtils.getSecurityManager();
DefaultWebSessionManager sessionManager = (DefaultWebSessionManager) securityManager.getSessionManager();
//获取当前已登录的用户session列表
Collection<Session> sessions = sessionManager.getSessionDAO().getActiveSessions();
Manager temp;
for(Session session : sessions) {
//清除该用户以前登录时保存的session,强制退出
Object attribute = session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
if (attribute == null) {
continue;
}
temp = (Manager) ((SimplePrincipalCollection) attribute).getPrimaryPrincipal();
if (token.getUsername().equals(temp.getUsername())) {
sessionManager.getSessionDAO().delete(session);
}
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
manager, //用户
manager.getUserpwd(), //密码
getName() //realm name
);
return authenticationInfo;
}
throw new UnknownAccountException();
}
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
// TODO Auto-generated method stub
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//获取登录时查询到的用户对象
Manager manager = (Manager)arg0.getPrimaryPrincipal();
//获取登录时查询到的用户对象
List<Resource> permissions = shiroService.getPermissionByid(manager.getId());
//把用户的所有权限添加到info中
for(Resource resource : permissions){
info.addStringPermission(resource.getUrl());
}
return info;
}
public void clearAuthz(){
this.clearCachedAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
}
}
6.配置ShiroUserFilter(解决我们项目前后端分离中出现跨域问题)
package com.longjie.yunxin.common.configuration;
/**
* @description: shiro跨域解决
* @author: 马志磊
* @create: 2019-06-26 17:45
*/
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.UserFilter;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* 重写shiro的UserFilter,实现通过OPTIONS请求
*
* @author MDY
*/
public class ShiroUserFilter extends UserFilter {
/**
* 在访问过来的时候检测是否为OPTIONS请求,如果是就直接返回true
*/
@Override
protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
Subject subject = SecurityUtils.getSubject();
Session s = subject.getSession();
HttpServletResponse httpResponse = (HttpServletResponse) response;
if(s==null){
//跳转到登陆界面
httpResponse.setHeader("result", "2");
return false;
}
HttpServletRequest httpRequest = (HttpServletRequest) request;
if (httpRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
setHeader(httpRequest, httpResponse);
return true;
}
return super.preHandle(request, response);
}
/**
* 该方法会在验证失败后调用,这里由于是前后端分离,后台不控制页面跳转
* 因此重写改成传输JSON数据
*/
@Override
protected void saveRequestAndRedirectToLogin(ServletRequest request, ServletResponse response) throws IOException {
saveRequest(request);
setHeader((HttpServletRequest) request, (HttpServletResponse) response);
}
/**
* 为response设置header,实现跨域
*/
private void setHeader(HttpServletRequest request, HttpServletResponse response) {
//跨域的header设置
response.setHeader("Access-control-Allow-Origin", request.getHeader("result"));
response.setHeader("Access-Control-Allow-Methods", request.getMethod());
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers"));
//防止乱码,适用于传输JSON数据
response.setHeader("Content-Type", "application/json;charset=UTF-8");
response.setStatus(HttpStatus.OK.value());
}
}
7.整合Redis
package com.longjie.yunxin.common.configuration;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.SessionKey;
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.session.mgt.WebSessionKey;
import org.apache.shiro.web.util.WebUtils;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.Serializable;
public class SessionManager extends DefaultWebSessionManager{
private static final String AUTHORIZATION = "token";
private static final String REFERENCED_SESSION_ID_SOURCE = "Stateless request";
public SessionManager() {
}
@Override
protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
//获取请求头,或者请求参数中的token
String id = StringUtils.isEmpty(WebUtils.toHttp(request).getHeader(AUTHORIZATION))
? request.getParameter(AUTHORIZATION) : WebUtils.toHttp(request).getHeader(AUTHORIZATION);
// 如果请求头中有 Token 则其值为sessionId
if (StringUtils.isNotEmpty(id)) {
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, REFERENCED_SESSION_ID_SOURCE);
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
return id;
} else {
// 否则按默认规则从cookie取sessionId
return super.getSessionId(request, response);
}
}
/**
* 获取session 优化单次请求需要多次访问redis的问题
*
* @param sessionKey
* @return
* @throws UnknownSessionException
*/
@Override
protected Session retrieveSession(SessionKey sessionKey) throws UnknownSessionException {
Serializable sessionId = getSessionId(sessionKey);
ServletRequest request = null;
if (sessionKey instanceof WebSessionKey) {
request = ((WebSessionKey) sessionKey).getServletRequest();
}
if (request != null && null != sessionId) {
Object sessionObj = request.getAttribute(sessionId.toString());
if (sessionObj != null) {
return (Session) sessionObj;
}
}
Session session = super.retrieveSession(sessionKey);
if (request != null && null != sessionId) {
request.setAttribute(sessionId.toString(), session);
}
return session;
}
}
8.无权限访问时,后端捕获异常并将状态返给前端
package com.longjie.yunxin.common.configuration;
import com.longjie.yunxin.entity.CommonCode;
import com.longjie.yunxin.entity.QueryResult;
import com.longjie.yunxin.entity.Result;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletResponse;
@ControllerAdvice
@ResponseBody
public class ExceptionAdvice {
/**
* shiro权限异常处理
* @return
*/
@ExceptionHandler(UnauthorizedException.class)
public Result unauthorizedException(HttpServletResponse response){
response.setHeader("result","4");//
QueryResult queryResult = new QueryResult();
return new Result(CommonCode.UNAUTHORISE, queryResult);
}
}
9.登陆接口
@CrossOrigin
@RestController
@RequestMapping("/login")
public class LoginController {
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
private RedisTemplate redisTemplate;
/**
* 后台系统登陆【马志磊修改6.15】
*
* @param userPhone
* @param userPwd
* @return
* @throws Exception
*/
@RequestMapping("/loginPCByPwd")
public Result loginPCByPwd(String userPhone, String userPwd) {
QueryResult queryResult = new QueryResult();
if (StringUtils.isEmpty(userPhone)) {
//用户为空
ExceptionCast.cast(CommonCode.PHONE_PARAM, "login", "loginPCByPwd");
}
if (StringUtils.isEmpty(userPwd)) {
//密码为空
ExceptionCast.cast(CommonCode.CODE_PARAM, "login", "loginPCByPwd");
}
//判断手机号和密码是否符合要求
if (!PhoneFormatCheckUtils.isChinaPhoneLegal(userPhone)) {
ExceptionCast.cast(CommonCode.PHONE_PARAM, "login", "loginPCByPwd");
}
//String newuserPwd = Md5Util.encodeByMd5(userPwd);
// 认证 Subject:主体
Subject subject = SecurityUtils.getSubject();
// 根据用户信息,组成用户令牌token
UsernamePasswordToken Token = new UsernamePasswordToken(userPhone, userPwd, true);
try {
subject.login(Token);
} catch (AuthenticationException e) {
return new Result(CommonCode.NULL_USER, queryResult);
}
Manager manager = (Manager) subject.getPrincipal();
JSON json = new JSONObject();
((JSONObject) json).put("token", subject.getSession().getId());
String token = subject.getSession().getId().toString();
//清除历史token
String userToken = stringRedisTemplate.opsForValue().get(userPhone + "web");
if (!StringUtils.isEmpty(userToken)) {
stringRedisTemplate.delete(userToken);
stringRedisTemplate.delete(userPhone + "web");
}
stringRedisTemplate.boundValueOps(userPhone + "web").set(token);
stringRedisTemplate.boundValueOps(token).set(JSON.toJSONString(manager));
queryResult.setToken(token);
queryResult.setData(manager);
return new Result(CommonCode.SUCCESS, queryResult);
}
}
10.同一个帐号最大会话数也可以有shiro完成,但是我接手本项目的时候已经实现了,不再赘述。
二.接下来是代码层的,除了单独对用户控制权限,其他的地方没什么绕的
1.Controller
package com.longjie.yunxin.controller.Shiro;
import com.longjie.yunxin.common.annotation.LogAnno;
import com.longjie.yunxin.common.exception.ExceptionCast;
import com.longjie.yunxin.entity.CommonCode;
import com.longjie.yunxin.entity.QueryResult;
import com.longjie.yunxin.entity.Result;
import com.longjie.yunxin.pojo.Permission;
import com.longjie.yunxin.pojo.Post;
import com.longjie.yunxin.pojo.Resource;
import com.longjie.yunxin.pojo.UserRole;
import com.longjie.yunxin.service.Shiro.ShiroService;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @Author 马志磊
* @Description: 权限部分的所有接口 共计18个
* @Return
* @Date 2019/6/24 14:01
*/
@CrossOrigin
@RestController
@RequestMapping("/shiro")
public class ShiroController {
@Autowired
private ShiroService shiroService;
//查询所有人的权限信息(对个人的权限配置考虑在权限表加上userid,关联起来,userid!=0时,再查询另一个sql)
@RequestMapping("/getPermission")
public Result getPsermission() {
QueryResult queryResult = new QueryResult();
List<Permission> permissions = shiroService.getPermission();
queryResult.setData(permissions);
return new Result(CommonCode.SUCCESS, queryResult);
}
//获取权限列表
@RequestMapping("/permissionList")
public Result PermissionList() {
QueryResult queryResult = new QueryResult();
List<Permission> permissions = shiroService.permissionList();
queryResult.setData(permissions);
return new Result(CommonCode.SUCCESS, queryResult);
}
//增加某个人的权限信息
@LogAnno(operateType = "增加某个人的权限信息")
@RequiresPermissions("/shiro/*")
@RequestMapping("/upPermById")
public Result upPermById(Integer userid, @RequestBody int permid[]) {
QueryResult queryResult = new QueryResult();
if (permid == null || permid.length == 0) {
ExceptionCast.cast(CommonCode.DATA_FAIL, "ShiroController", "upPermById");
}
shiroService.upPermById(userid, permid);
return new Result(CommonCode.SUCCESS, queryResult);
}
//获取所有的角色信息
@RequiresPermissions("/shiro/*")
@RequestMapping("/getRole")
public Result getRole() {
QueryResult queryResult = new QueryResult();
queryResult.setData(shiroService.getRole());
return new Result(CommonCode.SUCCESS, queryResult);
}
//增加分组
@LogAnno(operateType = "增加分组")
@RequiresPermissions("/shiro/*")
@RequestMapping("/addRole")
public Result addRole(String name, @RequestBody int array[]) {
if (StringUtils.isEmpty(name)) {
ExceptionCast.cast(CommonCode.DATA_FAIL, "ShiroController", "addRole");
}
if (array == null || array.length == 0) {
ExceptionCast.cast(CommonCode.DATA_FAIL, "ShiroController", "addRole");
}
QueryResult queryResult = new QueryResult();
shiroService.addRole(name, array);
return new Result(CommonCode.SUCCESS, queryResult);
}
//修改分组权限
@LogAnno(operateType = "修改分组权限")
@RequiresPermissions("/shiro/*")
@RequestMapping("/updateRole")
public Result updateRole(String name, Integer id, @RequestBody int array[]) {
if (id == null || "".equals(id)) {
ExceptionCast.cast(CommonCode.DATA_FAIL, "ShiroController", "updateRole");
}
if (StringUtils.isEmpty(name)) {
ExceptionCast.cast(CommonCode.DATA_FAIL, "ShiroController", "updateRole");
}
if (array == null || array.length == 0) {
ExceptionCast.cast(CommonCode.DATA_FAIL, "ShiroController", "updateRole");
}
QueryResult queryResult = new QueryResult();
shiroService.updateRole(name, id, array);
return new Result(CommonCode.SUCCESS, queryResult);
}
//查看分组对应的权限
@RequestMapping("/getPerById")
public Result getPerById(Integer roleid) {
if (roleid == null || "".equals(roleid)) {
ExceptionCast.cast(CommonCode.DATA_FAIL, "ShiroController", "getPerById");
}
QueryResult queryResult = new QueryResult();
queryResult.setData(shiroService.getRoleByID(roleid));
return new Result(CommonCode.SUCCESS, queryResult);
}
//删除分组
@LogAnno(operateType = "删除分组")
@RequiresPermissions("/shiro/*")
@RequestMapping("/deleteRole")
public Result deleteRole(Integer roleid) {
if (roleid == null || "".equals(roleid)) {
ExceptionCast.cast(CommonCode.DATA_FAIL, "ShiroController", "deleteRole");
}
QueryResult queryResult = new QueryResult();
shiroService.deleteRoleByID(roleid);
return new Result(CommonCode.SUCCESS, queryResult);
}
//组内成员信息列表
@RequiresPermissions("/shiro/*")
@RequestMapping("/queryInRole")
public Result queryInRole(Integer roleid) {
QueryResult queryResult = new QueryResult();
List<UserRole> list = shiroService.queryInRole(roleid);
queryResult.setData(list);
return new Result(CommonCode.SUCCESS, queryResult);
}
//查看组内某个成员的权限列表(Resource)
@RequiresPermissions("/shiro/*")
@RequestMapping("/getPermByID")
public Result getPermByID(Integer id) {
if (id == null) {
ExceptionCast.cast(CommonCode.DATA_FAIL, "ShiroController", "getPermByID");
}
QueryResult queryResult = new QueryResult();
List<Resource> list = shiroService.getPermissionByid(id);
queryResult.setData(list);
return new Result(CommonCode.SUCCESS, queryResult);
}
//向添加成员:姓名,手机号,密码(初始密码同手机号),roleid(向成员表和成员角色表同时插入数据),职位id
@LogAnno(operateType = "添加用户")
@RequiresPermissions("/shiro/*")
@RequestMapping("/addManager")
public Result addManager(String userName, String userPhone, Integer roleid, Integer postid) {
if (StringUtils.isEmpty(userName) || StringUtils.isEmpty(userPhone) ||
roleid == null || "".equals(roleid) || postid == null || "".equals(postid)) {
ExceptionCast.cast(CommonCode.DATA_FAIL, "ShiroController", "addManager");
}
QueryResult queryResult = new QueryResult();
shiroService.addManager(userName, userPhone, roleid, postid);
return new Result(CommonCode.SUCCESS, queryResult);
}
/**
* @Author 马志磊
* @Description: 后台用户密码修改
* @Return
* @Date 2019/6/26 14:44
*/
@LogAnno(operateType = "后台用户密码修改")
@RequiresPermissions("/shiro/*")
@RequestMapping("/updatePwdByPhone")
public Result updatePwdByPhone(String userPhone, String oldpwd, String newPwd) {
if (StringUtils.isEmpty(userPhone) || StringUtils.isEmpty(oldpwd) || StringUtils.isEmpty(newPwd)) {
ExceptionCast.cast(CommonCode.DATA_FAIL, "ShiroController", "updatePwdByPhone");
}
QueryResult queryResult = new QueryResult();
try {
shiroService.updatePwdByPhone(userPhone, oldpwd, newPwd);
return new Result(CommonCode.SUCCESS, queryResult);
} catch (Exception e) {
return new Result(CommonCode.CODE_PARAM, queryResult);
}
}
//获取职位列表
@RequiresPermissions("/shiro/*")
@RequestMapping("/postList")
public Result postList() {
QueryResult queryResult = new QueryResult();
List<Post> posts = shiroService.postList();
queryResult.setData(posts);
return new Result(CommonCode.SUCCESS, queryResult);
}
//增加职位
@LogAnno(operateType = "增加职位")
@RequiresPermissions("/shiro/*")
@RequestMapping("/addPost")
public Result addPost(String name) {
if (StringUtils.isEmpty(name)) {
ExceptionCast.cast(CommonCode.DATA_FAIL, "ShiroController", "addPost");
}
QueryResult queryResult = new QueryResult();
queryResult.setData(shiroService.addPost(name));
return new Result(CommonCode.SUCCESS, queryResult);
}
//删除组成员
@LogAnno(operateType = "后台删除组成员")
@RequiresPermissions("/shiro/*")
@RequestMapping("/deleteManager")
public Result deleteManager(Integer id) {
if (id == null || "".equals(id)) {
ExceptionCast.cast(CommonCode.DATA_FAIL, "ShiroController", "deleteManager");
}
QueryResult queryResult = new QueryResult();
shiroService.deleteManager(id);
return new Result(CommonCode.SUCCESS, queryResult);
}
/**
* @Author 马志磊
* @Description: 修改职位
* @Return
* @Date 2019/7/6 9:09
*/
@LogAnno(operateType = "修改职位")
@RequiresPermissions("/shiro/*")
@RequestMapping("/updatePost")
public Result updatePost(@RequestBody Post post) {
if (post == null) {
ExceptionCast.cast(CommonCode.DATA_FAIL, "ShiroController", "updatePost");
}
QueryResult queryResult = new QueryResult();
shiroService.updatePost(post);
return new Result(CommonCode.SUCCESS, queryResult);
}
/**
* @Author 马志磊
* @Description: 删除职位
* @Return
* @Date 2019/7/6 11:09
*/
@LogAnno(operateType = "删除职位")
@RequiresPermissions("/shiro/*")
@RequestMapping("/deletePost")
public Result deletePost(Integer id) {
if (id == null || "".equals(id)) {
ExceptionCast.cast(CommonCode.DATA_FAIL, "ShiroController", "deletePost");
}
QueryResult queryResult = new QueryResult();
shiroService.deletePost(id);
return new Result(CommonCode.SUCCESS, queryResult);
}
}
(通过去重实现此功能,所以只能较组内成员增加权限,不能减少)
2.Service
package com.longjie.yunxin.service.Shiro;
import com.longjie.yunxin.pojo.*;
import java.util.List;
public interface ShiroService {
//根据手机号查询用户
Manager selectManagerByPhone(String phone);
//获取所有的权限信息
List<Permission> getPermission();
//获取所有的权限信息
List<Permission> permissionList();
//修改某人的权限信息
void upPermById(Integer userid, int permid[]);
//根据id获取个人的权限信息
List<Resource> getPermissionByid(Integer id);
//获取所有的权限信息
List<Role> getRole();
//增加分组信息并关联权限
void addRole(String name, int array[]);
//修改分组信息和权限
void updateRole(String name, Integer id, int array[]);
//查询角色的权限
Role getRoleByID(Integer roleid);
//删除角色
void deleteRoleByID(Integer roleid);
//查询组内的信息
List<UserRole> queryInRole(Integer roleid);
//添加成员
void addManager(String userName, String userPhone, Integer roleid, Integer postid);
//修改密码
void updatePwdByPhone(String userPhone, String oldpwd, String newPwd) throws Exception;
//职位列表
List<Post> postList();
//增加职位
int addPost(String name);
//删除组成员
void deleteManager(Integer id);
//修改职位
void updatePost(Post post);
//删除职位
int deletePost(Integer id);
}
3.ServicreImpl
package com.longjie.yunxin.service.Shiro.impl;
import com.longjie.yunxin.common.exception.ExceptionCast;
import com.longjie.yunxin.common.util.Md5Util;
import com.longjie.yunxin.controller.Shiro.CommonController;
import com.longjie.yunxin.entity.CommonCode;
import com.longjie.yunxin.mapper.ShiroMapper;
import com.longjie.yunxin.pojo.*;
import com.longjie.yunxin.service.Shiro.ShiroService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.*;
import java.util.stream.Collectors;
@Service
public class ShiroServiceImpl implements ShiroService {
@Autowired
private ShiroMapper shiroMapper;
@Override
public Manager selectManagerByPhone(String phone) {
return shiroMapper.selectManagerByPhone(phone);
}
@Override
public List<Permission> getPermission() {
return shiroMapper.selectPerm();
}
@Override
public List<Permission> permissionList() {
return shiroMapper.permissionList();
}
@Transactional
@Override
public void upPermById(Integer userid, int permid[]) {
//先清除所有权限
int updateNum = permid.length;
List<Integer> ids = shiroMapper.findIdByManageerID(userid);
int num = ids.size();
if (updateNum > num) {
for (int i = 0; i < num; i++) {
shiroMapper.UpPermById(ids.get(i), new Integer(permid[i]));
}
for(int i = updateNum-1; i >= num; i--) {
shiroMapper.addPermById(userid,new Integer(permid[i]) );
}
}
else if (updateNum == num) {
for (int i = 0; i < num; i++) {
shiroMapper.UpPermById(ids.get(i), new Integer(permid[i]));
}
}
else if (updateNum < num) {
for (int i = 0; i < updateNum; i++) {
shiroMapper.UpPermById(ids.get(i), new Integer(permid[i]));
}
for (int i = num-1; i >= updateNum; i--) {
shiroMapper.deleteMyPerByID(ids.get(i));
}
}
//清除所有用户的权限缓存
CommonController.clearAuth();
}
@Override
public List<Resource> getPermissionByid (Integer id){
//组权限
List<Resource> permissions = shiroMapper.getPermissionByid(id);
//个人权限
List<Resource> permissions2 = shiroMapper.selectUserPermByid(id);
//合并权限
permissions.addAll(permissions2);
//利用 TreeSet的排序去重构造函数来达到去重元素的目的
//根据权限id去重
List<Resource> distinctList = null;
if (permissions.size() > 0) {
distinctList = permissions.stream()
.collect(Collectors.collectingAndThen(Collectors.toCollection(
() -> new TreeSet<>(Comparator.comparing(Resource::getId))), ArrayList::new));
} else {
ExceptionCast.cast(CommonCode.UNAUTHORISE, "ShiroServiceImpl", "getPermissionByid");//此人没有任何权限
}
return distinctList;
}
@Override
public List<Role> getRole () {
List<Role> list = shiroMapper.selectRole();
if (list.size() > 0) {
for (Role role :
list) {
role.setNum(shiroMapper.getRoleNum(role.getId()));
System.out.println(role);
}
}
return list;
}
@Transactional
@Override
public void addRole (String name,int array[]){
Role role = new Role(name);
shiroMapper.addRole(role);
if (array != null) {
Integer a = role.getId();
for (Integer rid :
array) {
shiroMapper.addResource(a, rid);
}
} else {
ExceptionCast.cast(CommonCode.DATA_FAIL, "ShiroServiceImpl", "addRole");
}
}
@Transactional
@Override
public void updateRole (String name, Integer id,@RequestParam int[] array){
shiroMapper.updateRoleName(name, id);
int updateNum = array.length;
List<Integer> ids = shiroMapper.findIdByRoleID(id);
int num = ids.size();
if (updateNum > num) {
for (int i = 0; i < num; i++) {
shiroMapper.updateRoleResource(ids.get(i), new Integer(array[i]));
}
for(int i = updateNum-1; i >= num; i--) {
shiroMapper.addResource(id,new Integer(array[i]) );
}
}
else if (updateNum == num) {
for (int i = 0; i < num; i++) {
shiroMapper.updateRoleResource(ids.get(i), new Integer(array[i]));
}
}
else if (updateNum < num) {
for (int i = 0; i < updateNum; i++) {
shiroMapper.updateRoleResource(ids.get(i), new Integer(array[i]));
}
for (int i = num-1; i >= updateNum; i--) {
shiroMapper.deleteOneRoleResourceByID(ids.get(i));
}
}
//清除所有用户的权限缓存
CommonController.clearAuth();
}
@Override
public Role getRoleByID (Integer roleid){
Role role = new Role();
List<Integer> PID = shiroMapper.getPermById(roleid);
List<Resource> list;
if (PID.size() > 0) {
list = shiroMapper.getPermName(PID);
role = shiroMapper.selectRoleByID(roleid);
role.setResource(list);
} else {
ExceptionCast.cast(CommonCode.DATA_FAIL, "ShiroServiceImpl", "getRoleByID");
}
return role;
}
@Transactional
@Override
public void deleteRoleByID (Integer roleid){
//删除用户与组的关联关系
shiroMapper.deleteUserRoleByRoleID(roleid);
//删除组与权限的关联关系
shiroMapper.deleteRoleResourceByID(roleid);
shiroMapper.deleteRoleByID(roleid);
}
@Override
public List<UserRole> queryInRole (Integer roleid){
return shiroMapper.queryInRole(roleid);
}
@Transactional
@Override
public void addManager (String userName, String userPhone, Integer roleid, Integer postid){
//密码默认为手机号
String userPwd = Md5Util.encodeByMd5(userPhone);
Date now = new Date();
//向manager表添加用户
//先通过手机号回查用户是否存在
Manager manager = shiroMapper.selectManagerByPhone(userPhone);
if (manager != null) {
ExceptionCast.cast(CommonCode.PHONE_REPEAT_REGISTER, "ShiroServiceImpl", "addManager");
}
Manager newManager = new Manager(userName, userPwd, userPhone, now);
shiroMapper.addManager(newManager);
//给用户关联角色
shiroMapper.addUserRole(new Integer(newManager.getId()), roleid);
//给用户添加职位
shiroMapper.addPost(new Integer(newManager.getId()), postid);
}
/**
* @Author 马志磊
* @Description 修改密码
* @Return a
* @Date 2019/6/26 14:43
*/
@Override
public void updatePwdByPhone (String userPhone, String oldpwd, String newPwd) throws Exception {
String Pwd = Md5Util.encodeByMd5(oldpwd);
//先通过手机号回查用户是否存在
Manager manager = shiroMapper.selectManagerByPhone(userPhone);
if (Pwd.equals(manager.getUserpwd())) {
String newpwd = Md5Util.encodeByMd5(newPwd);
shiroMapper.updatePwd(userPhone, newpwd);
} else {
ExceptionCast.cast(CommonCode.DATA_FAIL, "ShiroServiceImpl", "updatePwdByPhone");
}
}
@Override
public List<Post> postList () {
return shiroMapper.postList();
}
@Override
public int addPost (String name){
return shiroMapper.addPostname(name);
}
@Transactional
@Override
public void deleteManager (Integer id){
//删除个人的权限关联关系
shiroMapper.deleteUserResourceByManID(id);
//删除用户表
shiroMapper.deleteManager(id);
//删除成员关联的职位
shiroMapper.deleteManagerPost(id);
//删除成员关联的角色
shiroMapper.deleteManagerRole(id);
// if (a + b + c != 3) {
// ExceptionCast.cast(CommonCode.FAIL, "ShiroServiceImpl", "deleteManager"); //操作失败,事物回滚
//
// }
}
@Override
public void updatePost (@RequestBody Post post){
shiroMapper.updatePost(post);
}
@Override
public int deletePost (Integer id){
return shiroMapper.deletePost(id);
}
}
4.Mapper
package com.longjie.yunxin.mapper;
import com.longjie.yunxin.pojo.*;
import io.lettuce.core.dynamic.annotation.Param;
import java.util.List;
public interface ShiroMapper {
//根据手机号查询用户
Manager selectManagerByPhone(String phone);
//获取所有人的组权限
List<Permission> selectPerm();
//权限列表
List<Permission> permissionList();
//添加个人权限
Integer addPermById(@Param("userid") Integer userid, @Param("permid") Integer permid);
Integer UpPermById(@Param("id") Integer id, @Param("permid") Integer permid);
//根据id查询个人分配权限
List<Resource> selectUserPermByid(Integer id);
//根据用户id获取个人的权限信息
List<Resource> getPermissionByid(Integer id);
//获取所有角色
List<Role> selectRole();
Role selectRoleByID(Integer id);
//根据角色id获取该角色的人数
Integer getRoleNum(Integer id);
//增加分组(角色)信息
Integer addRole(Role role);
//修改分组信息
Integer updateRoleName(@Param("name") String name, @Param("id") Integer id);
//删除分组对应的权限
Integer deleteRoleResourceByID(Integer roleid);
//关联角色的资源
Integer addResource(@Param("roleid") Integer roleid, @Param("resourceid") Integer resourceid);
//根据roleid查询其权限id
List<Integer> getPermById(Integer roleid);
//查询角色名
List<Resource> getPermName(List permid);
//删除分组
Integer deleteRoleByID(Integer roleid);
//查询组内信息
List<UserRole> queryInRole(Integer roleid);
//向manager添加成员
Integer addManager(Manager manager);
//根据成员id,角色id关联角色
Integer addUserRole(@Param("managerid") Integer managerid, @Param("roleid") Integer roleid);
//根据成员id,职位id关联职位
Integer addPost(@Param("managerid") Integer managerid, @Param("postid") Integer postid);
//修该密码
Integer updatePwd(@Param("userPhone") String userPhone, @Param("newPwd") String newPwd);
//查询所有职位
List<Post> postList();
//增加职位
Integer addPostname(String name);
//删除组成员
Integer deleteManager(Integer id);
//删除成员关联的职位
Integer deleteManagerPost(Integer id);
//删除成员关联的角色
Integer deleteManagerRole(Integer id);
//修改职位
Integer updatePost(Post post);
//删除职位
Integer deletePost(Integer id);
//查询此用户的权限条数
List<Integer> findIdByManageerID(Integer id);
//根据id删除个人权限
Integer deleteMyPerByID(Integer id);
//根据组id查询组内权限条数
List<Integer> findIdByRoleID(Integer id);
//根据role_resource表id修改组权限
void updateRoleResource(@Param("id") Integer id, @Param("resourceId") Integer resourceId);
//根据role_resource表id删除
void deleteOneRoleResourceByID(Integer id);
//根据组ID查询组内成员ID
Integer deleteUserRoleByRoleID(Integer roleId);
//根据用户ID删除个人的权限关联关系
Integer deleteUserResourceByManID(Integer ManagerID);
}
5.mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.longjie.yunxin.mapper.ShiroMapper">
<select id="selectManagerByPhone" resultType="com.longjie.yunxin.pojo.Manager">
select * from manager where userPhone=#{phone}
</select>
<select id="selectPerm" resultType="com.longjie.yunxin.pojo.Permission">
select u.id,u.username,u.userPhone,re.name,re.url from role r
inner join user_role ur on ur.role_id=r.id
inner join manager u on u.id=ur.user_id
inner join role_resource rr on rr.role_id=r.id
inner join resource re on re.id=rr.resource_id
</select>
<select id="permissionList" resultType="com.longjie.yunxin.pojo.Permission">
select * from resource
</select>
<select id="selectUserPermByid" resultType="com.longjie.yunxin.pojo.Resource">
select r.id,r.name,r.url,u.userName from user_resource ur
inner join manager u on ur.user_id=u.id
inner join resource r on ur.resource_id=r.id
where u.id=#{id,jdbcType=INTEGER}
</select>
<select id="getPermissionByid" resultType="com.longjie.yunxin.pojo.Resource">
select re.id,re.name,re.url ,u.userName from role r
inner join user_role ur on ur.role_id=r.id
inner join manager u on u.id=ur.user_id
inner join role_resource rr on rr.role_id=r.id
inner join resource re on re.id=rr.resource_id
where u.id=#{id,jdbcType=INTEGER}
</select>
<select id="addPermById" parameterType="java.lang.Integer">
insert into user_resource(user_id,resource_id) values(#{userid,jdbcType=INTEGER},#{permid,jdbcType=INTEGER})
</select>
<select id="UpPermById" parameterType="java.lang.Integer">
update user_resource set resource_id=#{permid,jdbcType=INTEGER} where id=#{id,jdbcType=INTEGER}
</select>
<select id="selectRole" resultType="com.longjie.yunxin.pojo.Role">
select * from role
</select>
<select id="selectRoleByID" resultType="com.longjie.yunxin.pojo.Role">
select * from role where id=#{id,jdbcType=INTEGER}
</select>
<select id="getRoleNum" parameterType="java.lang.Integer" resultType="java.lang.Integer">
select count(*) from user_role ur where ur.role_id = #{id,jdbcType=INTEGER}
</select>
<insert id="addRole" useGeneratedKeys="true" keyProperty="id" parameterType="com.longjie.yunxin.pojo.Role">
insert into role(name) value(#{name})
</insert>
<update id="updateRoleName">
update role set name=#{name} where id=#{id,jdbcType=INTEGER}
</update>
<insert id="addResource" parameterType="java.lang.Integer">
insert into role_resource(role_id,resource_id) values(#{roleid},#{resourceid})
</insert>
<select id="getPermById" parameterType="java.lang.Integer" resultType="java.lang.Integer">
select resource_id from role_resource rs where rs.role_id = #{roleid}
</select>
<select id="getPermName" parameterType="java.lang.Integer" resultType="com.longjie.yunxin.pojo.Resource">
select * from resource r where r.id in
<foreach item="permid" collection="list"
open="(" separator="," close=")">
#{permid}
</foreach>
</select>
<delete id="deleteRoleByID" parameterType="java.lang.Integer">
delete from role where role.id=#{roleid}
</delete>
<select id="queryInRole" parameterType="java.lang.Integer" resultType="com.longjie.yunxin.pojo.UserRole">
select u.id id,u.userName name,u.userPhone phone,p.postName postname, u.userCreatedTime userCreatedTime,ur.status status,r.name rolename,ur.isuse isuse
from user_role ur
inner join manager u on ur.user_id=u.id
inner join role r on r.id=ur.role_id
inner join manager_post mp on mp.user_id=u.id
inner join post p on mp.post_id=p.id
where ur.role_id=#{roleid,jdbcType=INTEGER}
</select>
<insert id="addManager" useGeneratedKeys="true" keyProperty="id" parameterType="com.longjie.yunxin.pojo.Manager">
insert into manager(userName,userPwd,userPhone,userCreatedTime) values (#{username,jdbcType=VARCHAR},#{userpwd,jdbcType=VARCHAR},
#{userphone,jdbcType=VARCHAR},#{usercreatedtime,jdbcType=DATE})
</insert>
<insert id="addUserRole">
insert into user_role(user_id,role_id) values (#{managerid,jdbcType=INTEGER},#{roleid,jdbcType=INTEGER})
</insert>
<insert id="addPost">
insert into manager_post(user_id,post_id) values (#{managerid,jdbcType=INTEGER},#{postid,jdbcType=INTEGER})
</insert>
<update id="updatePwd">
update manager set userPwd=#{newPwd,jdbcType=VARCHAR} where userPhone=#{userPhone,jdbcType=VARCHAR}
</update>
<select id="postList" resultType="com.longjie.yunxin.pojo.Post">
select * from post
</select>
<insert id="addPostname">
insert into post(postName) values(#{name})
</insert>
<delete id="deleteManager" parameterType="java.lang.Integer">
delete from manager where id=#{id,jdbcType=INTEGER}
</delete>
<delete id="deleteManagerPost" parameterType="java.lang.Integer">
delete from manager_post where user_id=#{id,jdbcType=INTEGER}
</delete>
<delete id="deleteManagerRole" parameterType="java.lang.Integer">
delete from user_role where user_id=#{id,jdbcType=INTEGER}
</delete>
<delete id="deleteRoleResourceByID" parameterType="java.lang.Integer">
delete from role_resource where role_id =#{roleid,jdbcType=INTEGER}
</delete>
<update id="updatePost" parameterType="post">
update post set postName =#{postName,jdbcType=VARCHAR} where id =#{id,jdbcType=INTEGER}
</update>
<delete id="deletePost" parameterType="java.lang.Integer">
delete from post where id=#{id,jdbcType=INTEGER}
</delete>
<select id="findIdByManageerID" resultType="java.lang.Integer" parameterType="java.lang.Integer">
select id from user_resource where user_id=#{id}
</select>
<delete id="deleteMyPerByID" parameterType="java.lang.Integer">
delete from user_resource where id=#{id}
</delete>
<select id="findIdByRoleID" resultType="java.lang.Integer" parameterType="java.lang.Integer">
select id from role_resource where role_id=#{id}
</select>
<update id="updateRoleResource" parameterType="java.lang.Integer">
update role_resource set resource_id =#{resourceId,jdbcType=VARCHAR} where id =#{id,jdbcType=INTEGER}
</update>
<delete id="deleteOneRoleResourceByID" parameterType="java.lang.Integer">
delete from role_resource where id=#{id}
</delete>
<select id="deleteUserRoleByRoleID" parameterType="java.lang.Integer">
delete from user_role where role_id=#{roleId}
</select>
<delete id="deleteUserResourceByManID" parameterType="java.lang.Integer" >
delete from user_resource where user_id=#{ManagerID}
</delete>
</mapper>
权限部分到此完成!
<这个需求的实现是有限制的:个人用户的权限不能少于此人所在的组的组权限,简单说就是只能给单独用户赋权,不能减少权限>