【Shiro】Shiro简介及常用配置介绍

01_Shiro是什么

  • Shiro一个授权和认证的这样一个框架
  • Shiro可以进行认证、授权、Cache的管理、Session的管理、RememberMe功能的实现、加密、退出等

其他常见安全拦截框架:Spring Security,OAuth2.0 协议等…

02_Shiro的核心组件

Shiro官方图

Shiro 三大核心组件Subject、Security Manager、Realms

  • Subject 表示待认证和授权的用户
    • Principal:用户名(还可以是用户信息的封装)
    • Credential:密码
    • Token:令牌(用户名+密码的封装)----进行进行认证的封装对象,这个的对象并不是前后分离的这个token
  • Security Manager :它是Shiro框架的核心,Shiro就是通过Security Manager来进行内部实例的管理,并通过它来提供安全管理的各种服务
    • Authenticator:认证器
    • Anthorizer:授权器
    • SessionManager:会话管理器
    • CacheManager:缓存管理器
  • Realm :相当于Shiro进行认证和授权的数据源,充当了Shiro与安全数据之间的“桥梁”或者“连接器”。也就是说,当对用户进行认证(登录)和授权(访问控制)验证时,Shiro会用应用配置的Realm中查找用户及其权限信息
    Shiro官方图

03_Shiro的核心功能

  • Anthentication 认证,验证用户是否有相应的身份—登录认证;
  • Authorization 授权,即权限验证;对已经通过认证的用户检查是否具有某个权限或者角色,从而控制是否能够进行某种操作;
  • Session Managment 会话管理,用户在认证成功之后创建会话,在没有退出之前,当前用户的所有信息都会保存在这个会话中;可以是普通的JavaSE应用,也可以是web应用;
  • Cryptography 加密,对敏感信息进行加密处理,shiro就提供这种加密机制;

支持的特性:

  • Web Support —— Shiro提供了过滤器,可以通过过滤器拦截web请求来处理web应用的访问控制
  • Caching —— Shiro可以缓存用户信息以及用户的角色权限信息,可以提高执行效率
  • Concurrency —— Shiro支持多线程应用
  • Testing —— 提供测试支持
  • Run As —— 允许一个用户以另一种身份去访问
  • Remeber Me —— 提供记住我权限级别

Shiro是一个安全框架,不提供用户、权限的维护(用户的权限管理需要自己去设计)

Shiro官方图

04_Shiro的基本使用

       //1.创建安全管理器
       DefaultSecurityManager securityManager = new DefaultSecurityManager();
       //2.创建realm
       IniRealm iniRealm = new IniRealm("classpath:shiro.ini");
       //3.将realm设置给安全管理器
       securityManager.setRealm(iniRealm);
       //4.将Realm设置给SecurityUtils工具
       SecurityUtils.setSecurityManager(securityManager);
       //5.通过SecurityUtils工具类获取subject对象
       Subject subject = SecurityUtils.getSubject();

       /*
       *认证流程
       **/
       //a.将认证帐号和密码封装到token对象中
       UsernamePasswordToken token = new UsernamePasswordToken(username,password);
       //b.通过subject对象调用login方法进行认证申请:
       boolean b = false;
       try{
           subject.login(token);
           b = true;
       }catch(IncorrectCredentialsException e){
           b = false;
       }
       System.out.println(b?"登录成功":"登录失败");
       /*
       *授权
       **/
       //判断是否有某个角色
       subject.hasRole("seller");

       //判断是否有某个权限
        subject.isPermitted("order-del");

05_Shiro的自定义Realm

/**
 * 1.创建一个类继承AuthorizingRealm类(实现了Realm接口的类)
 * 2.重写doGetAuthorizationInfo和doGetAuthenticationInfo方法
 * 3.重写getName方法返回当前realm的一个自定义名称
 */
public class MyRealm extends AuthorizingRealm {

    @Autowired
    private UserDao userDao;

    @Override
    public String getName() {
        return "myRealm";
    }

    /**
     * 获取授权数据:权限角色管理
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
   		 //获取用户的用户名
        Object username = principalCollection.getPrimaryPrincipal();
        //根据用户名查询当前用户的角色列表
        List<String> permissionList = userDao.findPermission(username.toString());
        //根据用户名查询当前用户的权限列表
        List<String> findList = userDao.findRole(username.toString());
        
        //将权限集合交给Shiro
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.addStringPermissions(permissionList);
        simpleAuthorizationInfo.addRoles(findList);
        return simpleAuthorizationInfo;
    }

    /**
     * 获取认证的安全数据:登录
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //参数authenticationToken就是传递的  subject.login(token)
        // 从token中获取用户名
        UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) authenticationToken;
        String username = usernamePasswordToken.getUsername();
        //根据用户名,从数据库查询当前用户的安全数据
        UserInfo userInfo = userDao.findUserInfoByAccount(username);

        /**
         * 参数1:当前用户用户名
         * 参数2:从数据库查询出来的安全密码
         * 参数3:realm的唯一名称
         */
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(userInfo.getAccount(),userInfo.getPassword(),getName());
        //将simpleAuthenticationInfo交给SecurityManager进行登录逻辑判断
        return simpleAuthenticationInfo;
    }
}

  • controller层
@RequestMapping("login")
    @ResponseBody
    public String login(String username,String password){
        try {
            UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);
            //登录成功就不会有异常
            subject.login(usernamePasswordToken);
			//判断是否有某个权限
       		subject.isPermitted("administrator");
       		 //没有权限会报错,有权限就不报错
            subject.checkPermission("administrator");       
  	    }catch (AuthenticationException e) {
            e.printStackTrace();
        }
        return "success";
    }

06_Shiro的授权

  • 过滤器授权
    在Shiro过滤器中对请求的url进行权限设置

    filterMap.put("/add.html","perms[adm:f:save]");
    
    //设置未授权访问的页面路径—当权限不足时显示此页面
    filter.setUnauthorizedUrl("/login.html");
    
  • 注解授权
    配置Spring对Shiro注解的支持:ShiroConfig.java
    在请求的控制器添加权限注解

    @Controller
    @RequestMapping("list")
    public class CustomerController {
    
        @RequestMapping("save")
        //如果没有 adm:f:save 权限,则不允许执行此方法
        @RequiresPermissions("adm:f:save")
        //    @RequiresRoles("")
        public String list(){
            System.out.println("----------->查询客户信息");
            return "a";
        }
    
    }
    

    通过全局异常处理,指定权限不足时的页面跳转

    @ControllerAdvice
    public class GlobalExceptionHandler {
        @ExceptionHandler
        public String doException(Exception e){
            if(e instanceof AuthorizationException){
                return  "excep ";
            }
            return null;
        }	
    }
    
  • 手动授权
    在代码中进行手动的权限校验

    Subject subject = SecurityUtils.getSubject();
    if(subject.isPermitted("adm:f:save")){
        return "有权限";
    }else{
        return "无权限";
    }
    
  • HTML授权
    在菜单页面只显示当前用户拥有权限操作的菜单

07_Shiro的标签使用

当用户认证进入到主页面之后,需要显示用户信息及当前用户的权限信息;Shiro就提供了一套标签用于在页面来进行权限数据的呈现

Shiro提供了可供JSP使用的标签以及Thymeleaf中标签

  • JSP页面中引用:
    <%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
    
  • Thymeleaf模版中引用:
    在pom.xml文件中导入thymeleaf模版对shiro标签支持的依赖
    <dependency>
        <groupId>com.github.theborakompanioni</groupId>
        <artifactId>thymeleaf-extras-shiro</artifactId>
        <version>2.0.0</version>
    </dependency>
    
    在ShiroConfig中配置Shiro的
    @Configuration
    public class ShiroConfig {
    
        @Bean
        public ShiroDialect getShiroDialect(){
            return new ShiroDialect();
        }
        //...
    }
    
    Thymeleaf模版中引入shiro的命名空间
    <html xmlns:th="http://www.thymeleaf.org"
          xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
        ...
    </html>
    

07-1_常用标签

  • guest,判断用户是否是游客身份,如果是游客身份则显示此标签内容
    <shiro:guest>
     ·····
    </shiro:guest>
    
  • user,判断用户是否是认证身份,如果是认证身份则显示此标签内容
  • principal,获取当前登录用户名
    <shiro:user>
        用户[<shiro:principal/>]欢迎您!
    </shiro:user>
    
  • hasRole,获取用户身份如果和name身份相等则显示此标签内容
    <shiro:hasRole name="admin">
    ·····
    </shiro:hasRole>
    
  • hasPermission,获取用户权限如果和name权限相等则显示此标签内容
     <shiro:hasPermission name="adm:f:save">
    	·····
     </shiro:hasPermission>
    

08_Shiro的配置

08-1_Shiro使用加密认证

敏感信息存储数据库时需要利用Shiro加密认证
在realm中加入MD5Hash等加密规则即可Shiro会自动进行加密认证

08-2_缓存使用

使用Shiro进行权限管理过程中,每次授权都会访问realm中的doGetAuthorizationInfo方法查询当前用户的角色及权限信息,如果系统的用户量比较大则会对数据库造成比较大的压力

Shiro支持缓存以降低对数据库的访问压力(缓存的是授权信息)

08-3_session管理

Shiro进行认证和授权是基于session实现的,Shiro包含了对session的管理

  • 如果需要对session进行管理
    • 自定义session管理器
    • 将自定义的session管理器设置给SecurityManager

08-4_记住我(rememberMe)

将用户对页面访问的权限分为三个级别:

  • 未认证
  • 记住我
  • 已认证

08-1_退出登录

  • 在Shiro过滤器中进行配置,配置logut对应的路径
    filterMap.put("/exit","logout");
    
  • 在页面的“退出”按钮上,跳转到logout对应的ur
    <a href="exit">退出</a>
    

08-1_Shiro多Realm配置

多个Realm的处理方式:

  • 链式处理(默认)
    多个Realm依次进行认证,有一个Realm为true则结果为true
  • 分支处理
    根据不同的条件从多个Realm中选择一个进行认证处理

Shiro的配置参考:
【Shiro】Shiro的MVC、SpringBoot整合配置及常用配置.
资料整合来自:Shiro官网.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值