zoukankan      html  css  js  c++  java
  • Shiro学习(21)授予身份及切换身份

    在一些场景中,比如某个领导因为一些原因不能进行登录网站进行一些操作,他想把他网站上的工作委托给他的秘书,但是他不想把帐号/密码告诉他秘书,只是想把工作委托给他;此时和我们可以使用Shiro的RunAs功能,即允许一个用户假装为另一个用户(如果他们允许)的身份进行访问。

    本章代码基于《第十六章 综合实例》,请先了解相关数据模型及基本流程后再学习本章。

    表及数据SQL

    请运行shiro-example-chapter21/sql/ shiro-schema.sql 表结构

    请运行shiro-example-chapter21/sql/ shiro-schema.sql 数据

    实体

    具体请参考com.github.zhangkaitao.shiro.chapter21包下的实体。

    Java代码  收藏代码
    1. public class UserRunAs implements Serializable {  
    2.     private Long fromUserId;//授予身份帐号  
    3.     private Long toUserId;//被授予身份帐号  
    4. }   

    该实体定义了授予身份帐号(A)与被授予身份帐号(B)的关系,意思是B帐号将可以假装为A帐号的身份进行访问。

    DAO

    具体请参考com.github.zhangkaitao.shiro.chapter21.dao包下的DAO接口及实现。

    Service

    具体请参考com.github.zhangkaitao.shiro.chapter21.service包下的Service接口及实现。 

    Java代码  收藏代码
    1. public interface UserRunAsService {  
    2.     public void grantRunAs(Long fromUserId, Long toUserId);  
    3.     public void revokeRunAs(Long fromUserId, Long toUserId);  
    4.     public boolean exists(Long fromUserId, Long toUserId);  
    5.     public List<Long> findFromUserIds(Long toUserId);  
    6.     public List<Long> findToUserIds(Long fromUserId);  
    7. }   

    提供授予身份、回收身份、关系存在判断及查找API。

    Web控制器RunAsController

    该控制器完成:授予身份/回收身份/切换身份功能。

    展示当前用户能切换到身份列表,及授予给其他人的身份列表:

    Java代码  收藏代码
    1. @RequestMapping  
    2. public String runasList(@CurrentUser User loginUser, Model model) {  
    3.     model.addAttribute("fromUserIds",   
    4.         userRunAsService.findFromUserIds(loginUser.getId()));  
    5.     model.addAttribute("toUserIds", userRunAsService.findToUserIds(loginUser.getId()));  
    6.     List<User> allUsers = userService.findAll();  
    7.     allUsers.remove(loginUser);  
    8.     model.addAttribute("allUsers", allUsers);  
    9.   
    10.     Subject subject = SecurityUtils.getSubject();  
    11.     model.addAttribute("isRunas", subject.isRunAs());  
    12.     if(subject.isRunAs()) {  
    13.         String previousUsername =  
    14.                 (String)subject.getPreviousPrincipals().getPrimaryPrincipal();  
    15.         model.addAttribute("previousUsername", previousUsername);  
    16.     }  
    17.     return "runas";  
    18. }   

    1、Subject.isRunAs():表示当前用户是否是RunAs用户,即已经切换身份了;

    2、Subject.getPreviousPrincipals():得到切换身份之前的身份,一个用户可以切换很多次身份,之前的身份使用栈数据结构来存储;

    授予身份

    把当前用户身份授予给另一个用户,这样另一个用户可以切换身份到该用户。

    Java代码  收藏代码
    1. @RequestMapping("/grant/{toUserId}")  
    2. public String grant(  
    3.         @CurrentUser User loginUser,  
    4.         @PathVariable("toUserId") Long toUserId,  
    5.         RedirectAttributes redirectAttributes) {  
    6.     if(loginUser.getId().equals(toUserId)) {  
    7.         redirectAttributes.addFlashAttribute("msg", "自己不能切换到自己的身份");  
    8.         return "redirect:/runas";  
    9.     }  
    10.     userRunAsService.grantRunAs(loginUser.getId(), toUserId);  
    11.     redirectAttributes.addFlashAttribute("msg", "操作成功");  
    12.     return "redirect:/runas";  
    13. }   

    1、自己不能授予身份给自己;

    2、调用UserRunAsService. grantRunAs把当前登录用户的身份授予给相应的用户;

    回收身份

    把授予给某个用户的身份回收回来。 

    Java代码  收藏代码
    1. @RequestMapping("/revoke/{toUserId}")  
    2. public String revoke(  
    3.         @CurrentUser User loginUser,  
    4.         @PathVariable("toUserId") Long toUserId,  
    5.         RedirectAttributes redirectAttributes) {  
    6.     userRunAsService.revokeRunAs(loginUser.getId(), toUserId);  
    7.     redirectAttributes.addFlashAttribute("msg", "操作成功");  
    8.     return "redirect:/runas";  
    9. }  

      

    切换身份

    Java代码  收藏代码
    1. @RequestMapping("/switchTo/{switchToUserId}")  
    2. public String switchTo(  
    3.         @CurrentUser User loginUser,  
    4.         @PathVariable("switchToUserId") Long switchToUserId,  
    5.         RedirectAttributes redirectAttributes) {  
    6.     Subject subject = SecurityUtils.getSubject();  
    7.     User switchToUser = userService.findOne(switchToUserId);  
    8.     if(loginUser.equals(switchToUser)) {  
    9.         redirectAttributes.addFlashAttribute("msg", "自己不能切换到自己的身份");  
    10.         return "redirect:/runas";  
    11.     }  
    12.     if(switchToUser == null || !userRunAsService.exists(switchToUserId, loginUser.getId())) {  
    13.         redirectAttributes.addFlashAttribute("msg", "对方没有授予您身份,不能切换");  
    14.         return "redirect:/runas";  
    15.     }  
    16.     subject.runAs(new SimplePrincipalCollection(switchToUser.getUsername(), ""));  
    17.     redirectAttributes.addFlashAttribute("msg", "操作成功");  
    18.     redirectAttributes.addFlashAttribute("needRefresh", "true");  
    19.     return "redirect:/runas";  
    20. }  
    21.    

    1、首先根据switchToUserId查找到要切换到的身份;

    2、然后通过UserRunAsService. exists()判断当前登录用户是否可以切换到该身份;

    3、通过Subject.runAs()切换到该身份;

    切换到上一个身份 

    Java代码  收藏代码
    1. @RequestMapping("/switchBack")  
    2. public String switchBack(RedirectAttributes redirectAttributes) {  
    3.     Subject subject = SecurityUtils.getSubject();  
    4.     if(subject.isRunAs()) {  
    5.        subject.releaseRunAs();  
    6.     }  
    7.     redirectAttributes.addFlashAttribute("msg", "操作成功");  
    8.     redirectAttributes.addFlashAttribute("needRefresh", "true");  
    9.     return "redirect:/runas";  
    10. }   

    1、通过Subject.releaseRunAs()切换会上一个身份;

    此处注意的是我们可以切换多次身份,如A切换到B,然后再切换到C;那么需要调用两次Subject. releaseRunAs()才能切换会A;即内部使用栈数据结构存储着切换过的用户;Subject. getPreviousPrincipals()得到上一次切换到的身份,比如当前是C;那么调用该API将得到B的身份。

    其他代码和配置和《第十六章 综合实例》一样,请参考该章。

    测试

    1、首先访问http://localhost:8080/chapter21/,输入admin/123456进行登录;会看到如下界面: 


     

    2、点击切换身份按钮,跳到如下界面:   

    在该界面可以授权身份给其他人(点击授权身份可以把自己的身份授权给其他人/点击回收身份可以把之前授予的身份撤回)、或切换到其他身份(即假装为其他身份运行);

    3、点击切换到该身份按钮,切换到相应的身份运行,如: 

    此时zhang用户切换到admin身份;如果点击切换回该身份,会把当前身份切换会zhang。

  • 相关阅读:
    164 Maximum Gap 最大间距
    162 Find Peak Element 寻找峰值
    160 Intersection of Two Linked Lists 相交链表
    155 Min Stack 最小栈
    154 Find Minimum in Rotated Sorted Array II
    153 Find Minimum in Rotated Sorted Array 旋转数组的最小值
    152 Maximum Product Subarray 乘积最大子序列
    151 Reverse Words in a String 翻转字符串里的单词
    bzoj3994: [SDOI2015]约数个数和
    bzoj 4590: [Shoi2015]自动刷题机
  • 原文地址:https://www.cnblogs.com/guoziyi/p/7131229.html
Copyright © 2011-2022 走看看