SpringBoot整合Shiro+Redis框架权限管理
这里用到的Redis参考我写的另一篇博客Redis+SpringBoot整合注解版
本文是我从项目中截取出来的,可能直接跑是跑不起来
一、导入依赖
<!-- shiro的依赖-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
<!-- shiro+redis缓存插件 -->
<dependency>
<groupId>org.crazycake</groupId>
<artifactId>shiro-redis</artifactId>
<version>3.1.0</version>
</dependency>
二、Config类
2.1、自定义realm
import com.example.arcsoft_Administration.lcy_module.service.UserService;
import com.example.arcsoft_Administration.public_module.entity.Permission;
import com.example.arcsoft_Administration.public_module.entity.Role;
import com.example.arcsoft_Administration.public_module.entity.User;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
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.springframework.beans.factory.annotation.Autowired;
import java.util.ArrayList;
import java.util.List;
/**
* 自定义realm
*/
public class CustomRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
/**
* 用户登录的时候会调用
*
* @param token
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("认证 doGetAuthenticationInfo");
//从token获取用户信息,token代表用户输入
String username = (String) token.getPrincipal();
User user = userService.findAllUserInfoByUsername(username);
user.toString();
//取密码
String pwd = user.getPassword();
if (pwd == null || "".equals(pwd)) {
return null;
}
return new SimpleAuthenticationInfo(user, user.getPassword(), this.getClass().getName());
}
/**
* 进行权限校验的时候回调用
*
* @param principals
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("授权 doGetAuthorizationInfo");
User newUser = (User) principals.getPrimaryPrincipal();
// newUser.toString();
User user = userService.findAllUserInfoByUsername(newUser.getUsername());
// user.toString();
//角色集合
List<String> stringRoleList = new ArrayList<>();
//权限集合
List<String> stringPermissionList = new ArrayList<>();
List<Role> roleList = user.getRoleList();
for (Role role : roleList) {
stringRoleList.add(role.getName());
List<Permission> permissionList = role.getPermissionList();
for (Permission p : permissionList) {
if (p != null) {
stringPermissionList.add(p.getName());
}
}
}
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
simpleAuthorizationInfo.addRoles(stringRoleList);
simpleAuthorizationInfo.addStringPermissions(stringPermissionList);
return simpleAuthorizationInfo;
}
}
2.2、自定义AuthorizationFilter
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/**
* 自定义权限拦截,原来是两个缺一不可现在是满足其中一个即可
* @author lichangyuan
* @create 2021-02-08 12:28
*/
public class CustomRolesOrAuthorizationFilter extends AuthorizationFilter {
@Override
protected boolean isAccessAllowed(ServletRequest req, ServletResponse resp, Object mappedValue) throws Exception {
Subject subject = getSubject(req, resp);
//获取当前访问路径所需要的角色集合
String[] rolesArray = (String[]) mappedValue;
//没有角色限制,有权限访问
if (rolesArray == null || rolesArray.length == 0) {
return true;
}
//当前subject是rolesArray(门槛条件)中的任何一个,则有权限访问
for (int i = 0; i < rolesArray.length; i++) {
if (subject.hasRole(rolesArray[i])) {
return true;
}
}
return false;
}
}
2.3、自定义SessionIdGenerator
自定义SessionId
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.SessionIdGenerator;
import java.io.Serializable;
import java.util.UUID;
/**
* 自定义sesionid生成
*/
public class CustomSessionIdGenerator implements SessionIdGenerator {
@Override
public Serializable generateId(Session session) {
return "ACE_"+UUID.randomUUID().toString().replace("-","");
}
}
2.4、自定义DefaultWebSessionManager
import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.util.WebUtils;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.Serializable;
public class CustomSessionManager extends DefaultWebSessionManager {
private static final String AUTHORIZATION = "token";
public CustomSessionManager(){
super();
}
@Override
protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
String sessionId = WebUtils.toHttp(request).getHeader(AUTHORIZATION);
if(sessionId != null){
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,
ShiroHttpServletRequest.COOKIE_SESSION_ID_SOURCE);
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, sessionId);
//automatically mark it valid here. If it is invalid, the
//onUnknownSession method below will be invoked and we'll remove the attribute at that time.
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
return sessionId;
}else {
return super.getSessionId(request,response);
}
}
}
2.5、ShiroConfig
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.annotation.RequiresPermissions;
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.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;
import javax.servlet.Filter;
import java.util.LinkedHashMap;
import java.util.Map;
@Configuration
public class ShiroConfig {
@Bean
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
System.out.println("执行 ShiroFilterFactoryBean.shiroFilter()");
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//必须设置securityManager
shiroFilterFactoryBean.setSecurityManager(securityManager);
//需要登录的接口,如果访问某个接口,需要登录却没登录,则调用此接口(如果不是前后端分离,则跳转页面)
shiroFilterFactoryBean.setLoginUrl("/pub/need_login");
//登录成功,跳转url,如果前后端分离,则没这个调用
shiroFilterFactoryBean.setSuccessUrl("/");
//没有权限,未授权就会调用此方法, 先验证登录-》再验证是否有权限
shiroFilterFactoryBean.setUnauthorizedUrl("/pub/not_permit");
//加载设置自定义的filter
Map<String, Filter> filterMap = new LinkedHashMap<>();
filterMap.put("roleOrFilter", new CustomRolesOrAuthorizationFilter());
shiroFilterFactoryBean.setFilters(filterMap);
//拦截器路径,坑一,部分路径无法进行拦截,时有时无;因为同学使用的是hashmap, 无序的,应该改为LinkedHashMap
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
//退出过滤器
// filterChainDefinitionMap.put("/logout","anon");
//匿名可以访问,也是就游客模式
filterChainDefinitionMap.put("/pub/**", "anon");
filterChainDefinitionMap.put("/file/**", "anon");
//有管理员编辑权限才可以访问
filterChainDefinitionMap.put("/authc/admin/**", "perms[admin_update]");
//有巡检员编辑权限才可以访问
filterChainDefinitionMap.put("/authc/inspector/**", "perms[inspector_update]");
//登录用户就可以访问的接口
filterChainDefinitionMap.put("/authc/**", "authc");
// //管理员和超管角色才可以访问的接口(比如修改)(我们自定义的AuthorizationFilter)
// filterChainDefinitionMap.put("/admin/**", "roleOrFilter[admin,root]");
// //巡检员和超管角色才可以访问的接口(比如修改)(我们自定义的AuthorizationFilter)
// filterChainDefinitionMap.put("/inspector/**", "roleOrFilter[inspector,root]");
//超管角色才可以访问的接口(比如修改和人员管理的接口)(我们自定义的AuthorizationFilter)
filterChainDefinitionMap.put("/root/**", "roleOrFilter[root]");
// //管理员角色才可以访问(与的关系)
// filterChainDefinitionMap.put("/admin/**", "roles[admin]");
//不拦截swagger
filterChainDefinitionMap.put("/swagger-ui.html", "anon");
filterChainDefinitionMap.put("/swagger-resources", "anon");
filterChainDefinitionMap.put("/v2/api-docs", "anon");
filterChainDefinitionMap.put("/webjars/springfox-swagger-ui/**", "anon");
filterChainDefinitionMap.put("/configuration/security", "anon");
filterChainDefinitionMap.put("/configuration/ui", "anon");
filterChainDefinitionMap.put("/webjars/**", "anon");
filterChainDefinitionMap.put("/configuration/**", "anon");
//坑二: 过滤链是顺序执行,从上而下,一般讲/** 放到最下面
//authc : url定义必须通过认证才可以访问
//anon : url可以匿名访问
filterChainDefinitionMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//如果不是前后端分离,则不必设置下面的sessionManager
securityManager.setSessionManager(sessionManager());
//使用自定义的cacheManager
securityManager.setCacheManager(CacheManager());
//设置realm(推荐放到最后,不然某些情况会不生效)
securityManager.setRealm(customRealm());
return securityManager;
}
/**
* 自定义realm
*
* @return
*/
@Bean
public CustomRealm customRealm() {
CustomRealm customRealm = new CustomRealm();
customRealm.setCredentialsMatcher(hashedCredentialsMatcher());
return customRealm;
}
/**
* 密码加解密规则
*
* @return
*/
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher() {
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
//设置散列算法:这里使用的MD5算法
credentialsMatcher.setHashAlgorithmName("md5");
//散列次数,好比散列2次,相当于md5(md5(xxxx))
credentialsMatcher.setHashIterations(2);
return credentialsMatcher;
}
//自定义sessionManager
@Bean
public SessionManager sessionManager() {
CustomSessionManager customSessionManager = new CustomSessionManager();
//超时时间,默认 30分钟,会话超时;方法里面的单位是毫秒
// customSessionManager.setGlobalSessionTimeout(1800000);
// 永不过期
customSessionManager.setGlobalSessionTimeout(-1000L);
//配置session持久化
customSessionManager.setSessionDAO(redisSessionDAO());
return customSessionManager;
}
/**
* 配置RedisManager
*
* @return
*/
public RedisManager getRedisManager() {
RedisManager redisManager = new RedisManager();
redisManager.setHost("localhost");
redisManager.setPort(6379);
return redisManager;
}
public RedisCacheManager CacheManager() {
RedisCacheManager redisCacheManager = new RedisCacheManager();
redisCacheManager.setRedisManager(getRedisManager());
//设置过期时间,单位是秒,权限校验的时才
redisCacheManager.setExpire(120);
return redisCacheManager;
}
/**
* 自定义session持久化
*
* @return
*/
public RedisSessionDAO redisSessionDAO() {
RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
//redis缓存
redisSessionDAO.setRedisManager(getRedisManager());
//设置sessionid生成器
redisSessionDAO.setSessionIdGenerator(new CustomSessionIdGenerator());
return redisSessionDAO;
}
/**
* 管理shiro一些bean的生命周期 即bean初始化 与销毁
*
* @return
*/
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
return new LifecycleBeanPostProcessor();
}
/**
* api controller 层面
* 加入注解的使用,不加入这个AOP注解不生效(shiro的注解 例如 @RequiresGuest)
*
* @return
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
return authorizationAttributeSourceAdvisor;
}
/**
* 用来扫描上下文寻找所有的Advistor(通知器),
* 将符合条件的Advisor应用到切入点的Bean中,需要在LifecycleBeanPostProcessor创建后才可以创建
*
* @return
*/
@Bean
@DependsOn("lifecycleBeanPostProcessor")
public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
defaultAdvisorAutoProxyCreator.setUsePrefix(true);
return defaultAdvisorAutoProxyCreator;
}
}
三、登陆注册及其他接口
3.1、Controller层
@RestController
@RequestMapping("pub")
@CrossOrigin//跨域
@Transactional(rollbackFor = Exception.class)//事物回滚
public class PublicController {
@Autowired
private UserService userService;
@Autowired
private CommonUtils commonUtils;
@RequestMapping("need_login")
public JsonData needLogin() {
return JsonData.buildError(-1, "温馨提示:请使用对应的账号登录");
}
@RequestMapping("not_permit")
public JsonData notPermit() {
return JsonData.buildError(-2, "温馨提示:拒绝访问,没权限");
}
/**
* 登录接口
*
* @param userQuery
* @param request
* @param response
* @return
*/
@PostMapping("login")
public JsonData login(@RequestBody UserQuery userQuery, HttpServletRequest request, HttpServletResponse response) {
Subject subject = SecurityUtils.getSubject();
Map<String, Object> info = new HashMap<>(16);
try {
// System.out.println(userQuery.getName()+userQuery.getPwd());
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(userQuery.getName(), userQuery.getPwd());
subject.login(usernamePasswordToken);
info.put("msg", "登录成功");
info.put("token", subject.getSession().getId());
return JsonData.buildSuccess(info);
} catch (Exception e) {
e.printStackTrace();
throw new LCYException(-1, "账号或者密码错误");
}
}
/**
* 获取用户基本信息
*
* @return
*/
@RequestMapping("api/getUserInfo")
public JsonData getinfo() {
try {
User principal = userService.findAllUserInfoByUsername(ShiroUtils.getUser().getUsername());
//User principal = ShiroUtils.getUser();
if (principal != null) {
//隐藏密码
principal.setPassword(null);
//返回数据存储map
Map<String, Object> resultinfo = new HashMap<>(16);
//储存基本信息
resultinfo.put("user_info", principal);
//储存信息中的角色
List<String> stringRoleList = new ArrayList<>();
List<Role> roleList = principal.getRoleList();
for (Role role : roleList) {
stringRoleList.add(role.getName());
}
resultinfo.put("roles", stringRoleList);
//查找用户的未读信息
int userId = ShiroUtils.getUser().getId();
Integer messageCounts = messageService.selectUserUnreadInformation(userId, 0);
resultinfo.put("messageCounts",messageCounts);
return JsonData.buildSuccess(resultinfo);
} else {
return JsonData.buildError("token无效");
}
} catch (Exception e) {
e.printStackTrace();
throw new LCYException(-1, "查询失败,可能参数原因(例如类型)");
}
}
/**
* 注册接口
*
* @param register_info
* @return
*/
@PostMapping("api/register")
public JsonData register(@RequestBody Map<String, Object> register_info) {
try {
if (!commonUtils.traversingMap(new Object[]{
register_info.get("username"),
register_info.get("password"),
register_info.get("name"),
register_info.get("sex"),
register_info.get("phone"),
register_info.get("department"),
register_info.get("company"),
register_info.get("address"),
register_info.get("pic")})) {
return JsonData.buildError("create");
}
User user = new User();
user.setUsername(String.valueOf(register_info.get("username")));
user.setPassword(String.valueOf(register_info.get("password")));
user.setName(String.valueOf(register_info.get("name")));
user.setSex(String.valueOf(register_info.get("sex")));
user.setPhone(String.valueOf(register_info.get("phone")));
user.setDepartment(String.valueOf(register_info.get("department")));
user.setCompany(String.valueOf(register_info.get("company")));
user.setAddress(String.valueOf(register_info.get("address")));
return userService.registerAndAddRole(user, String.valueOf(register_info.get("create")));
} catch (Exception e) {
e.printStackTrace();
throw new LCYException(-1, "查询失败,可能参数原因(例如类型)");
}
}
/**
* 退出接口
*
* @return
*/
@RequestMapping("logout")
public JsonData findMyPlayRecord() {
try {
Subject subject = SecurityUtils.getSubject();
if (subject.getPrincipals() == null) {
return JsonData.buildError("退出登陆失败(token错误)");
}
SecurityUtils.getSubject().logout();
return JsonData.buildSuccess("退出登录成功");
} catch (Exception e) {
e.printStackTrace();
throw new LCYException(-1, "查询失败,可能参数原因(例如类型)");
}
}
}
3.2、Service层
3.2.1、UserService
public interface UserService {
/**
* 获取全部用户信息,包括角色,权限
* @param username
* @return
*/
User findAllUserInfoByUsername(String username);
/**
* 获取用户基本信息
* @param userId
* @return
*/
User findSimpleUserInfoById(int userId);
/**
* 根据用户名查找用户信息
* @param username
* @return
*/
User findSimpleUserInfoByUsername(String username);
/**
* 接收添加用户并赋予默认的权限
* @param user
* @param create
* @return
*/
JsonData registerAndAddRole(User user,String create);
}
3.2.2、UserServiceImpl
@Service
public class UserServiceImpl implements UserService {
@Autowired
private RoleMapper roleMapper;
@Autowired
private UserMapper userMapper;
@Autowired
CommonUtils commonUtils;
@Override
@Cacheable(value = "user-redis-cache", key = "'UserService'+'findAllUserInfoByUsername'+#username")
public User findAllUserInfoByUsername(String username) {
//第一次查找只返回用户的基础信息
User user = userMapper.findByUsername(username);
//第二次查找返回用户的角色集合,并查找每个角色的权限集合
List<Role> roleList = roleMapper.findRoleListByUserId(user.getId());
//添加到user中
user.setRoleList(roleList);
return user;
}
@Override
@Cacheable(value = "user-redis-cache", key = "'UserService'+'findSimpleUserInfoById'+#userId")
public User findSimpleUserInfoById(int userId) {
return userMapper.findById(userId);
}
@Override
@Cacheable(value = "user-redis-cache", key = "'UserService'+'findSimpleUserInfoByUsername'+#username")
public User findSimpleUserInfoByUsername(String username) {
return userMapper.findByUsername(username);
}
@Override
@CacheEvict(value = "user-redis-cache", allEntries = true)
public JsonData registerAndAddRole(User user, String create) {
if (commonUtils.strIsEmpty(user.getUsername()) || commonUtils.strIsEmpty(user.getPassword()) || commonUtils.strIsEmpty(user.getName()) || commonUtils.strIsEmpty(user.getCompany())) {
return JsonData.buildError("账户,密码,姓名,公司不能为空");
}
if (userMapper.findByUsername(user.getUsername()) == null) {
Integer roleId;
String remarks;
// if ("0".equals(create)) {
// roleId = roleMapper.findRoleIdByRoleName("user");
// remarks = user.getUsername() + "是" + "普通用户";
// } else {
//如果创建公司已存在
if (userMapper.findCompany(user.getCompany()) != 0) {
return JsonData.buildError("该公司已存在,不能创建");
}
userMapper.insertCompany(user.getCompany());
roleId = roleMapper.findRoleIdByRoleName("root");
remarks = user.getUsername() + "是" + "超级管理员";
//}
//给密码加密
user.setPassword(commonUtils.MD5(user.getPassword()));
//设置时间
user.setCreateTime(new Date());
//添加用户
userMapper.addUser(user);
//添加用户权限
userMapper.addUserRole(user.getId(), roleId, remarks);
// int i=1/0;
return JsonData.buildSuccess("注册成功");
} else {
return JsonData.buildError("注册失败,该用户已存在");
}
}
}
3.3、Mapper层
RoleMapper
import com.example.arcsoft_Administration.public_module.entity.Role;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.mapping.FetchType;
import java.util.List;
public interface RoleMapper {
/**
* 查找角色集合通过用户id
*
* @param userId
* @return
*/
@Select("select ur.role_id as id, " +
"r.name as name, " +
"r.description as description " +
" from user_role ur left join role r on ur.role_id = r.id " +
"where ur.user_id = #{userId}")
@Results(
value = {
@Result(id = true, property = "id", column = "id"),
@Result(property = "name", column = "name"),
@Result(property = "description", column = "description"),
@Result(property = "permissionList", column = "id",
many = @Many(select = "com.example.arcsoft_Administration.lcy_module.mapper.PermissionMapper.findPermissionListByRoleId", fetchType = FetchType.DEFAULT)
)
}
)
List<Role> findRoleListByUserId(@Param("userId") int userId);
/**
* 查找角色id通过姓名
* @param roleName
* @return
*/
Integer findRoleIdByRoleName(@Param("roleName") String roleName);
/**
* 查找角色描述通过id
* @param roleId
* @return
*/
String findRoleDescriptionById(@Param("roleId") Integer roleId);
}
userMapper
import com.example.arcsoft_Administration.public_module.entity.User;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface UserMapper {
/**
* 查找用户通过名字
*
* @param username
* @return
*/
@Select("select * from user where username = #{username}")
User findByUsername(@Param("username") String username);
/**
* 查找用户通过id
*
* @param id
* @return
*/
@Select("select * from user where id=#{userId}")
User findById(@Param("userId") int id);
/**
* 查找用户通过账号和密码
*
* @param username
* @param pwd
* @return
*/
@Select("select * from user where username = #{username} and password = #{pwd}")
User findByUsernameAndPwd(@Param("username") String username, @Param("pwd") String pwd);
/**
* 添加用户返回id值
*
* @param user
* @return
*/
Integer addUser(User user);
/**
* 赋予用户不同的角色
*
* @param userId
* @param roleId
* @param remarks
*/
void addUserRole(@Param("userId") Integer userId, @Param("roleId") Integer roleId, @Param("remarks") String remarks);
}
PermissionMapper
import com.example.arcsoft_Administration.public_module.entity.Equipment;
import com.example.arcsoft_Administration.public_module.entity.Permission;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import java.util.List;
public interface PermissionMapper {
/**
* 查找权限集合通过角色id
* @param roleId
* @return
*/
@Select("select p.id as id, p.name as name, p.url as url from role_permission rp " +
"left join permission p on rp.permission_id=p.id " +
"where rp.role_id= #{roleId} ")
List<Permission> findPermissionListByRoleId(@Param("roleId") int roleId);
}
3.4、Entity实体类
3.4.1、Role
public class Role implements Serializable {
private int id;
private String name;
private String description;
//权限集合
private List<Permission> permissionList;
}
3.4.2、User
public class User implements Serializable {
private int id;
private String username;
private String password;
private String name;
}
3.4.3、UserQuery
public class UserQuery implements Serializable {
private String name;
private String pwd;
}
3.4.4、UserRole
public class UserRole implements Serializable {
private int id;
private int userId;
private int roleId;
}
3.5、数据库设计
四、Shiro相关的自定义工具类
4.1、ShiroUtils
import com.example.arcsoft_Administration.public_module.entity.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.Subject;
/**
* @author lichangyuan
* @create 2021-03-04 10:05
*/
public class ShiroUtils {
/**
* @return
*/
public static Subject getSubjct() {
return SecurityUtils.getSubject();
}
/**
* 获取用户信息
*
* @return
*/
public static User getUser() {
return (User) getSubjct().getPrincipal();
}
/**
* 切换身份,登录后,动态更改subject的用户属性
*
* @param newUserInfo
*/
public static void setUser(User newUserInfo) {
Subject subject = SecurityUtils.getSubject();
PrincipalCollection principalCollection = subject.getPrincipals();
String realmName = principalCollection.getRealmNames().iterator().next();
PrincipalCollection newPrincipalCollection =
new SimplePrincipalCollection(newUserInfo, realmName);
subject.runAs(newPrincipalCollection);
}
}
4.2、CommonUtils
@Component
public class CommonUtils {
/**
* MD5加密工具类
*
* @param data
* @return
*/
public String MD5(String data) {
String hashName = "md5";
Object result = new SimpleHash(hashName, data, null, 2);
return String.valueOf(result);
}
/**
* 判断字符串是否为空
*
* @param str
* @return
*/
public boolean strIsEmpty(String str) {
if (str == null || str.length() <= 0 || str == "null") {
return true;
} else {
return false;
}
}
/**
* 判断字符串是否为空
*
* @param str
* @return
*/
// public boolean strIsEmpty2(String str) {
// if (str != null && str.length() != 0) {
// return true;
// } else {
// return false;
// }
// }
/**
* 获取当前时间
*/
public Date getNowTime() {
return new Date();
}
// Date date = new Date();
// SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// format.setTimeZone(TimeZone.getTimeZone("GMT+8"));
// String currentTime = format.format(date);
// //将String类型转换成date类型,主要格式必须是yyyy-MM-dd HH:mm:ss相同
// try {
// Date newTime=format.parse(currentTime);
// return newTime;
// } catch (ParseException e) {
// e.printStackTrace();
// }
// return null;
/**
* 分页查询,传入参数分别是,结果,总数量,一次数量
*/
public Map getResultInfo(Object resultRecords, Integer totalNumber, Integer OneTimeTotal) {
Map result = new HashMap<>(16);
//总页数
Integer resultPages = 0;
if (totalNumber % OneTimeTotal > 0) {
resultPages = totalNumber / OneTimeTotal + 1;
} else {
resultPages = totalNumber / OneTimeTotal;
}
result.put("result_records", resultRecords);
result.put("result_pages", resultPages);
result.put("result_counts", totalNumber);
return result;
}
/**
* 获得一个UUID
*
* @return String UUID
*/
public String getUUID() {
String uuid = UUID.randomUUID().toString();
//去掉“-”符号
return uuid.replaceAll("-", "");
}
/**
* object转换成时间
*
* @param s
* @return
* @throws ParseException
*/
public Date convertTimeType(Object s) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
format.setTimeZone(TimeZone.getTimeZone("GMT+8"));
Date date;
try {
date = format.parse((String) s);
} catch (Exception e) {
date = null;
}
// date=format.parse((String) s);
return date;
}
/**
* 生成指定长度的uuid
*/
public String getCustomLengthUUID(Integer length) {
return UUID.randomUUID().toString().replaceAll("-", "").substring(0, length);
}
/**
* 自定义生成指定长度的uuid
*/
public String getCustomPrefixAndLengthUUID(String str, Integer length) {
return str + UUID.randomUUID().toString().replaceAll("-", "").substring(0, length);
}
/**
* 如果有有空值返回false
*
* @param objects
* @return
*/
public boolean traversingMap(Object[] objects) {
for (Object o : objects) {
if (o == null) {
return false;
}
}
return true;
}
}
4.3、JsonData
@ApiModel("接口实体类")
public class JsonData implements Serializable{
/**
* 状态码 0表示成功过,-1,-2,-3、、、为失败
*/
@ApiModelProperty("状态码 0表示成功过,-1,-2,-3、、、为失败")
private Integer code;
/**
* 业务数据
*/
@ApiModelProperty("业务数据")
private Object data;
/**
* 信息表示
*/
@ApiModelProperty("信息表示")
private String msg;
public JsonData() {
}
public JsonData(Integer code, Object data, String msg) {
this.code = code;
this.data = data;
this.msg = msg;
}
/**
* 成功,不用返回数据
*
* @return
*/
public static JsonData buildSuccess() {
return new JsonData(0, null, null);
}
/**
* 成功,返回数据
*
* @param data
* @return
*/
public static JsonData buildSuccess(Object data) {
return new JsonData(0, data, null);
}
/**
* 失败,固定状态码
*
* @param msg
* @return
*/
public static JsonData buildError(String msg) {
return new JsonData(-1, null, msg);
}
/**
* 失败,自定义错误码和信息
*
* @param code
* @param msg
* @return
*/
public static JsonData buildError(Integer code, String msg) {
return new JsonData(code, null, msg);
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
}