本文源码:GitHub·点这里 || GitEE·点这里

一、Shiro简介

1、基础概念

Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。作为一款安全框架Shiro的设计相当巧妙。Shiro的应用不依赖任何容器,它不仅可以在JavaEE下使用,还可以应用在JavaSE环境中。

2、核心角色

1)Subject:认证主体

代表当前系统的使用者,就是用户,在Shiro的认证中,认证主体通常就是userName和passWord,或者其他用户相关的唯一标识。

2)SecurityManager:安全管理器

Shiro架构中最核心的组件,通过它可以协调其他组件完成用户认证和授权。实际上,SecurityManager就是Shiro框架的控制器。

3)Realm:域对象

定义了访问数据的方式,用来连接不同的数据源,如:关系数据库,配置文件等等。

3、核心理念

Shiro自己不维护用户和权限,通过Subject用户主体和Realm域对象的注入,完成用户的认证和授权。

二、整合SpringBoot2框架

1、核心依赖

<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>

2、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<String, String> 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;
}
}

3、域对象配置

@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<String> permsList;
//默认用户拥有最高权限
List<SysMenuEntity> menuList = sysMenuMapper.selectList();
permsList = new ArrayList<>(menuList.size());
for(SysMenuEntity menu : menuList){
permsList.add(menu.getPerms());
}
//用户权限列表
Set<String> 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);
}
}

4、核心工具类

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();
}
}

5、自定义权限异常提示

@RestControllerAdvice
public class ShiroException {
@ExceptionHandler(AuthorizationException.class)
public String authorizationException (){
return "抱歉您没有权限访问该内容!";
}
@ExceptionHandler(Exception.class)
public String handleException(Exception e){
return "系统异常!";
}
}

三、案例演示代码

1、测试接口

@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" ;
}
}

2、测试流程

1)、登录后取得权限
http://localhost:7011/userLogin?userName=admin&passWord=admin
2)、访问有权限接口
http://localhost:7011/menu/list
3)、访问无权限接口
http://localhost:7011/menu/list2
4)、退出登录
http://localhost:7011/userLogOut

四、源代码地址

GitHub·地址
https://github.com/cicadasmile/middle-ware-parent
GitEE·地址
https://gitee.com/cicadasmile/middle-ware-parent

SpringBoot2.0 整合 Shiro 框架,实现用户权限管理的更多相关文章

  1. SpringBoot2.0 整合 Dubbo框架 ,实现RPC服务远程调用

    一.Dubbo框架简介 1.框架依赖 图例说明: 1)图中小方块 Protocol, Cluster, Proxy, Service, Container, Registry, Monitor 代表层 ...

  2. SpringBoot2.0 整合 SpringSecurity 框架,实现用户权限安全管理

    本文源码:GitHub·点这里 || GitEE·点这里 一.Security简介 1.基础概念 Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方 ...

  3. 7. 整合shiro,搭建粗粒度权限管理

    shiro是一个易用的权限管理框架,只需提供一个Realm即可在项目中使用,本文就将结合上一篇中搭建的权限模块.角色模块和用户模块来搭建一个粗粒度的权限管理系统,具体如下:1. 添加shiro依赖和与 ...

  4. SpringBoot2.0 整合 JWT 框架,解决Token跨域验证问题

    本文源码:GitHub·点这里 || GitEE·点这里 一.传统Session认证 1.认证过程 1.用户向服务器发送用户名和密码. 2.服务器验证后在当前对话(session)保存相关数据. 3. ...

  5. SpringBoot2.0 整合 ElasticSearch框架,实现高性能搜索引擎

    本文源码:GitHub·点这里 || GitEE·点这里 一.安装和简介 ElasticSearch是一个基于Lucene的搜索服务器.它提供了一个分布式多用户能力的全文搜索引擎,基于RESTful ...

  6. springboot2.0整合shiro出现ShiroDialect报错 找不到org/thymeleaf/processor/attr/AbstractTextChildModifierAttrPr

    包版本过低,找最新包 https://mvnrepository.com/ <dependency> <groupId>com.github.theborakompanioni ...

  7. springboot2.0整合shiro遇到的问题

    1.重启服务器,访问登陆页面,登陆成功后跳转的不是index,而是favicon.ico

  8. (十二)整合 Shiro 框架,实现用户权限管理

    整合 Shiro 框架,实现用户权限管理 1.Shiro简介 1.1 基础概念 1.2 核心角色 1.3 核心理念 2.SpringBoot整合Shiro 2.1 核心依赖 2.2 Shiro核心配置 ...

  9. (补漏)Springboot2.0 集成shiro权限管理

    原文Springboot2.0 集成shiro权限管理 一.关于停止使用外键. 原本集成shiro建立用户.角色.权限表的时候使用了外键,系统自动创建其中两个关联表,用@JoinTable.看起来省事 ...

随机推荐

  1. 说说 WebSocket,3 分钟让你全面认识它

    "WebSocket 是一项先进的技术,它可以在用户的浏览器和服务器之间打开交互式通信会话.通过 WebSocket,您可以向服务器发送消息并实时接收响应,而无需通过传统的轮询服务器的方式来 ...

  2. 阿里云https证书Apache配置

    最近玩小程序,只支持https协议,于是给网站添加https支持.手上没钱,自己生成的证书不受信任,找到了阿里云的免费证书(PS:证书可以用在其他云主机上,不一定是阿里云的主机).如何购买下载不多说, ...

  3. 2016/11/10 kettle概述

    ETL(Extract-Transform-Load,即抽取,转换,加载),数据仓库技术,是用来处理将数据从来源(以前做的项目)经过抽取,转换,加载到达目的端(正在做的项目)的过程.也就是新的项目需要 ...

  4. 深入理解Kafka必知必会(3)

    Kafka中的事务是怎么实现的? Kafka中的事务可以使应用程序将消费消息.生产消息.提交消费位移当作原子操作来处理,同时成功或失败,即使该生产或消费会跨多个分区. 生产者必须提供唯一的transa ...

  5. Shell—详解$( )、$(( ))、``与${ }的区别

    https://www.jianshu.com/p/2237f029c385 https://www.cnblogs.com/chenpython123/p/11052276.html https:/ ...

  6. (办公)记事本_Linux权限

    参考谷粒学院Linux教程:http://www.gulixueyuan.com/course/300/task/7084/show# linux权限,什么用户可以操作什么. 1.基本权限的作用: 1 ...

  7. Spring cloud Feign 深度学习与应用

    简介 Spring Cloud Feign是一个声明式的Web Service客户端,它的目的就是让Web Service调用更加简单.Feign提供了HTTP请求的模板,通过编写简单的接口和插入注解 ...

  8. Dubbo学习系列之六(微服务架构实战)

    看了最近文章的反馈,似乎波澜不惊的样子,应该是看官觉得都是小菜,那我就直上硬菜,人狠话不多,开始!准备:Idea201902/JDK11/ZK3.5.5/Gradle5.4.1/RabbitMQ3.7 ...

  9. js 淡入淡出的tab选项卡

    代码如下 <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF- ...

  10. 25.Zabbix入门必备

    ==Zabbix入门必备== 1.配置zabbix源 [root@zabbix ~]# cat /etc/yum.repos.d/zabbix.repo [zabbix] name=Zabbix Of ...