(十二)整合 Shiro 框架,实现用户权限管理
整合 Shiro 框架,实现用户权限管理
1、Shiro简介
1.1 基础概念
Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。作为一款安全框架Shiro的设计相当巧妙。Shiro的应用不依赖任何容器,它不仅可以在JavaEE下使用,还可以应用在JavaSE环境中。
1.2 核心角色
Subject:认证主体
代表当前系统的使用者,就是用户,在Shiro的认证中,认证主体通常就是userName和passWord,或者其他用户相关的唯一标识。SecurityManager:安全管理器
Shiro架构中最核心的组件,通过它可以协调其他组件完成用户认证和授权。实际上,SecurityManager就是Shiro框架的控制器。Realm:域对象
定义了访问数据的方式,用来连接不同的数据源,如:关系数据库,配置文件等等。
1.3 核心理念
Shiro自己不维护用户和权限,通过Subject用户主体和Realm域对象的注入,完成用户的认证和授权。
2、SpringBoot整合Shiro
2.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.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;
}
}
2.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);
}
}
3.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();
}
}
3.5 自定义权限异常提示
@RestControllerAdvice
public class ShiroException {
@ExceptionHandler(AuthorizationException.class)
public String authorizationException (){
return "抱歉您没有权限访问该内容!";
}
@ExceptionHandler(Exception.class)
public String handleException(Exception e){
return "系统异常!";
}
}
3、案例演示代码
3.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" ;
}
}
3.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
(十二)整合 Shiro 框架,实现用户权限管理的更多相关文章
- 7. 整合shiro,搭建粗粒度权限管理
shiro是一个易用的权限管理框架,只需提供一个Realm即可在项目中使用,本文就将结合上一篇中搭建的权限模块.角色模块和用户模块来搭建一个粗粒度的权限管理系统,具体如下:1. 添加shiro依赖和与 ...
- 十二、基于Django实现RBAC权限管理
一.RBAC概述 RBAC(Role-Based Access Control,基于角色的访问控制),通过角色绑定权限,然后给用户划分角色. 从企业的角度来说,基本上是按照角色来划分职能.比如,CEO ...
- (十三)整合 SpringSecurity 框架,实现用户权限管理
整合 SpringSecurity 框架,实现用户权限管理 1.Security简介 1.1 基础概念 1.2 核心API解读 2.SpringBoot整合SpringSecurity 2.1 流程描 ...
- Spring Boot(十四):spring boot整合shiro-登录认证和权限管理
Spring Boot(十四):spring boot整合shiro-登录认证和权限管理 使用Spring Boot集成Apache Shiro.安全应该是互联网公司的一道生命线,几乎任何的公司都会涉 ...
- springboot(十四):springboot整合shiro-登录认证和权限管理(转)
springboot(十四):springboot整合shiro-登录认证和权限管理 .embody{ padding:10px 10px 10px; margin:0 -20px; border-b ...
- spring整合shiro框架
上一篇文章已经对shiro框架做了一定的介绍,这篇文章讲述使用spring整合shiro框架,实现用户认证已经权限控制 1.搭建环境 这里不在赘述spring环境的搭建,可以简单的搭建一个ssm框架, ...
- ClickHouse学习系列之二【用户权限管理】
背景 最近花了些时间看了下ClickHouse文档,发现它在OLAP方面表现很优异,而且相对也比较轻量和简单,所以准备入门了解下该数据库系统.在安装完之后首先做的应该如何设置用户密码以及权限控制.因为 ...
- Python 学习 第十篇 CMDB用户权限管理
Python 学习 第十篇 CMDB用户权限管理 2016-10-10 16:29:17 标签: python 版权声明:原创作品,谢绝转载!否则将追究法律责任. 不管是什么系统,用户权限都是至关重要 ...
- ASP.NET MVC+EF框架+EasyUI实现权限管理系列(21)-用户角色权限基本的实现说明
原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(21)-用户角色权限基本的实现说明 ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇) (1):框 ...
随机推荐
- codeforces 1438D,思路非常非常巧妙的构造题
大家好,欢迎来到codeforces专题. 今天选择的问题是contest1438的D题,全场通过人数为1325人.一般在codeforces当中千人通过的题难度都不算太高,但是这题有点例外,虽然没有 ...
- 本地显示Linux服务器的GUI程序
如果我们UI自动化脚本跑在 Linux 服务器环境上,这个时候我们是看不到界面的,如果不使用浏览器的无头模式,这个时候我们的程序就跑不起来了,如何在服务器环境不使用浏览器的无头模式下进行UI测试呢,我 ...
- TurtleBot3 Waffle (tx2版华夫)(8)键盘控制
1)[Remote PC] 启动roscore $ roscore 2)[Turbot3] 启动turbot3 $ roslaunch turbot3_bringup minimal.launch 3 ...
- Github不为人知的一个功能,一个小彩蛋
Github 是一个基于Git的代码托管平台,相信很多人都用过,当然这些"很多人"中大部分都是程序员.当你在Github上创建仓库时(Github称项目为仓库),你会给这个仓库添加 ...
- Java的nanoTime()方法
java有两个获取和时间相关的秒数方法,一个是广泛使用的 System.currentTimeMillis() 返回的是从一个长整型结果,表示毫秒. 另一个是 System.nanoTime() 返回 ...
- 我的程序员之路:自学Java篇
序章 时光疾驰,从事IT行业已两年有余. 16年11月开始自学Java,从此开启自学之路,后来实习期自学大数据.python.爬虫等,最终成长为一名平凡的程序员.回首望去,一路上的过往历历在目,有初学 ...
- js 数组的方法总结
1.Array.map() 此方法是将数组中的每个元素调用一个提供的函数,结果作为一个新的数组返回,并没有改变原来的数组 let arr = [1, 2, 3, 4, 5] let newAr ...
- Linux学习笔记 | 配置ssh
目录: SSH的必要性 将默认镜像源修改为清华镜像源 Linux安装ssh软件 使用putty软件实现ssh连接 Windows下安装winscp SSH的必要性 一般服务器都位于远程而非本地,或者及 ...
- 跨站脚本漏洞(XSS)基础
什么是跨站脚本攻击XSS 跨站脚本(cross site script),为了避免与样式css混淆所以简称为XSS,是一种经常出现在web应用中的计算机安全漏洞,也是web中最主流的攻击方式. 什么是 ...
- 【Linux】cron
每五分钟执行 */5 * * * * 每小时执行 0 * * * * 0 */1 * * * 效果相同 每天执行 0 0 * * * 每周执行 0 0 ...