原博客地址:http://jinnianshilongnian.iteye.com/blog/2018398

根据下载的pdf学习。

第二十一章 授予身份与切换身份(一)

1.使用场景

某个领导因为某些原因不能访问一些网站,他想把这个网站上的工作委托给秘书,但是他又不想提供账户、密码。此时可以使用shiro的 RunAs 功能。

RunAs:允许一个用户假装为另一个用户(如果获得了允许)的身份进行访问。

注意,本章代码基于《第十六章 综合实例》,详细的数据模型及基本流程见该章。

2.表及数据

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

 drop table if exists sys_user;
drop table if exists sys_organization;
drop table if exists sys_resource;
drop table if exists sys_role;
drop table if exists sys_user_runas; create table sys_user (
id bigint auto_increment,
organization_id bigint,
username varchar(100),
password varchar(100),
salt varchar(100),
role_ids varchar(100),
locked bool default false,
constraint pk_sys_user primary key(id)
) charset=utf8 ENGINE=InnoDB;
create unique index idx_sys_user_username on sys_user(username);
create index idx_sys_user_organization_id on sys_user(organization_id); create table sys_organization (
id bigint auto_increment,
name varchar(100),
parent_id bigint,
parent_ids varchar(100),
available bool default false,
constraint pk_sys_organization primary key(id)
) charset=utf8 ENGINE=InnoDB;
create index idx_sys_organization_parent_id on sys_organization(parent_id);
create index idx_sys_organization_parent_ids on sys_organization(parent_ids); create table sys_resource (
id bigint auto_increment,
name varchar(100),
type varchar(50),
url varchar(200),
parent_id bigint,
parent_ids varchar(100),
permission varchar(100),
available bool default false,
constraint pk_sys_resource primary key(id)
) charset=utf8 ENGINE=InnoDB;
create index idx_sys_resource_parent_id on sys_resource(parent_id);
create index idx_sys_resource_parent_ids on sys_resource(parent_ids); create table sys_role (
id bigint auto_increment,
role varchar(100),
description varchar(100),
resource_ids varchar(100),
available bool default false,
constraint pk_sys_role primary key(id)
) charset=utf8 ENGINE=InnoDB;
create index idx_sys_role_resource_ids on sys_role(resource_ids); create table sys_user_runas (
from_user_id bigint,
to_user_id bigint,
constraint pk_sys_user_runas primary key(from_user_id, to_user_id)
) charset=utf8 ENGINE=InnoDB;

shiro-schema.sql

 DELIMITER ;
delete from sys_user;
delete from sys_role;
delete from sys_resource;
delete from sys_organization;
delete from sys_user_runas; insert into sys_user values(1,1,'admin','d3c59d25033dbf980d29554025c23a75','8d78869f470951332959580424d4bf4f', '1', false);
insert into sys_user values(2,1,'zhang','c6a02f6c9a5aaf311ec94009b6b024d0','588ae709311808bd7e5fade1c84407c7', '1', false);
insert into sys_user values(3,1,'wang','2e6f83bdaef108d4f23b2a1f2b9928cc','bd647b15f6724ea711272c4a3c6d16c0', '1', false); insert into sys_organization values(1, '总公司', 0, '0/', true);
insert into sys_organization values(2, '分公司1', 1, '0/1/', true);
insert into sys_organization values(3, '分公司2', 1, '0/1/', true);
insert into sys_organization values(4, '分公司11', 2, '0/1/2/', true); insert into sys_resource values(1, '资源', 'menu', '', 0, '0/', '', true); insert into sys_resource values(11, '组织机构管理', 'menu', '/organization', 1, '0/1/', 'organization:*', true);
insert into sys_resource values(12, '组织机构新增', 'button', '', 11, '0/1/11/', 'organization:create', true);
insert into sys_resource values(13, '组织机构修改', 'button', '', 11, '0/1/11/', 'organization:update', true);
insert into sys_resource values(14, '组织机构删除', 'button', '', 11, '0/1/11/', 'organization:delete', true);
insert into sys_resource values(15, '组织机构查看', 'button', '', 11, '0/1/11/', 'organization:view', true); insert into sys_resource values(21, '用户管理', 'menu', '/user', 1, '0/1/', 'user:*', true);
insert into sys_resource values(22, '用户新增', 'button', '', 21, '0/1/21/', 'user:create', true);
insert into sys_resource values(23, '用户修改', 'button', '', 21, '0/1/21/', 'user:update', true);
insert into sys_resource values(24, '用户删除', 'button', '', 21, '0/1/21/', 'user:delete', true);
insert into sys_resource values(25, '用户查看', 'button', '', 21, '0/1/21/', 'user:view', true); insert into sys_resource values(31, '资源管理', 'menu', '/resource', 1, '0/1/', 'resource:*', true);
insert into sys_resource values(32, '资源新增', 'button', '', 31, '0/1/31/', 'resource:create', true);
insert into sys_resource values(33, '资源修改', 'button', '', 31, '0/1/31/', 'resource:update', true);
insert into sys_resource values(34, '资源删除', 'button', '', 31, '0/1/31/', 'resource:delete', true);
insert into sys_resource values(35, '资源查看', 'button', '', 31, '0/1/31/', 'resource:view', true); insert into sys_resource values(41, '角色管理', 'menu', '/role', 1, '0/1/', 'role:*', true);
insert into sys_resource values(42, '角色新增', 'button', '', 41, '0/1/41/', 'role:create', true);
insert into sys_resource values(43, '角色修改', 'button', '', 41, '0/1/41/', 'role:update', true);
insert into sys_resource values(44, '角色删除', 'button', '', 41, '0/1/41/', 'role:delete', true);
insert into sys_resource values(45, '角色查看', 'button', '', 41, '0/1/41/', 'role:view', true); insert into sys_role values(1, 'admin', '超级管理员', '11,21,31,41', true);

shiro-data.sql

增加的sql语句:

 drop table if exists sys_user_runas;
create table sys_user_runas (
from_user_id bigint,
to_user_id bigint,
constraint pk_sys_user_runas primary key(from_user_id, to_user_id)
) charset=utf8 ENGINE=InnoDB;

3.实体entity

 package com.github.zhangkaitao.shiro.chapter21.entity;
import java.io.Serializable; public class Organization implements Serializable {
private Long id; //编号
private String name; //组织机构名称
private Long parentId; //父编号
private String parentIds; //父编号列表,如1/2/
private Boolean available = Boolean.FALSE; //getter、setter略 public boolean isRootNode() {
return parentId == 0;
} public String makeSelfAsParentIds() {
return getParentIds() + getId() + "/";
} @Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false; Organization that = (Organization) o; if (id != null ? !id.equals(that.id) : that.id != null) return false; return true;
} @Override
public int hashCode() {
return id != null ? id.hashCode() : 0;
} @Override
public String toString() {
return "Organization{" +
"id=" + id +
", name='" + name + '\'' +
", parentId=" + parentId +
", parentIds='" + parentIds + '\'' +
", available=" + available +
'}';
}
}

Organization

 package com.github.zhangkaitao.shiro.chapter21.entity;
import java.io.Serializable; public class Resource implements Serializable {
private Long id; //编号
private String name; //资源名称
private ResourceType type = ResourceType.menu; //资源类型
private String url; //资源路径
private String permission; //权限字符串
private Long parentId; //父编号
private String parentIds; //父编号列表
private Boolean available = Boolean.FALSE; public static enum ResourceType {
menu("菜单"), button("按钮"); private final String info;
private ResourceType(String info) {
this.info = info;
} public String getInfo() {
return info;
}
} //getter、setter略 public boolean isRootNode() {
return parentId == 0;
} public String makeSelfAsParentIds() {
return getParentIds() + getId() + "/";
} @Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false; Resource resource = (Resource) o; if (id != null ? !id.equals(resource.id) : resource.id != null) return false; return true;
} @Override
public int hashCode() {
return id != null ? id.hashCode() : 0;
} @Override
public String toString() {
return "Resource{" +
"id=" + id +
", name='" + name + '\'' +
", type=" + type +
", permission='" + permission + '\'' +
", parentId=" + parentId +
", parentIds='" + parentIds + '\'' +
", available=" + available +
'}';
}
}

Resource

 package com.github.zhangkaitao.shiro.chapter21.entity;

 import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List; public class Role implements Serializable {
private Long id; //编号
private String role; //角色标识 程序中判断使用,如"admin"
private String description; //角色描述,UI界面显示使用
private List<Long> resourceIds; //拥有的资源
private Boolean available = Boolean.FALSE; //是否可用,如果不可用将不会添加给用户 public Role() {
} public Role(String role, String description, Boolean available) {
this.role = role;
this.description = description;
this.available = available;
} //getter、setter略
public List<Long> getResourceIds() {
if(resourceIds == null) {
resourceIds = new ArrayList<Long>();
}
return resourceIds;
} public void setResourceIds(List<Long> resourceIds) {
this.resourceIds = resourceIds;
} public String getResourceIdsStr() {
if(CollectionUtils.isEmpty(resourceIds)) {
return "";
}
StringBuilder s = new StringBuilder();
for(Long resourceId : resourceIds) {
s.append(resourceId);
s.append(",");
}
return s.toString();
} public void setResourceIdsStr(String resourceIdsStr) {
if(StringUtils.isEmpty(resourceIdsStr)) {
return;
}
String[] resourceIdStrs = resourceIdsStr.split(",");
for(String resourceIdStr : resourceIdStrs) {
if(StringUtils.isEmpty(resourceIdStr)) {
continue;
}
getResourceIds().add(Long.valueOf(resourceIdStr));
}
} @Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false; Role role = (Role) o; if (id != null ? !id.equals(role.id) : role.id != null) return false; return true;
} @Override
public int hashCode() {
return id != null ? id.hashCode() : 0;
} @Override
public String toString() {
return "Role{" +
"id=" + id +
", role='" + role + '\'' +
", description='" + description + '\'' +
", resourceIds=" + resourceIds +
", available=" + available +
'}';
}
}

Role

 package com.github.zhangkaitao.shiro.chapter21.entity;

 import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List; public class User implements Serializable {
private Long id; //编号
private Long organizationId; //所属公司
private String username; //用户名
private String password; //密码
private String salt; //加密密码的盐
private List<Long> roleIds; //拥有的角色列表
private Boolean locked = Boolean.FALSE; public User() {
} public User(String username, String password) {
this.username = username;
this.password = password;
} //getter、setter略 public String getCredentialsSalt() {
return username + salt;
} public List<Long> getRoleIds() {
if(roleIds == null) {
roleIds = new ArrayList<Long>();
}
return roleIds;
} public void setRoleIds(List<Long> roleIds) {
this.roleIds = roleIds;
} public String getRoleIdsStr() {
if(CollectionUtils.isEmpty(roleIds)) {
return "";
}
StringBuilder s = new StringBuilder();
for(Long roleId : roleIds) {
s.append(roleId);
s.append(",");
}
return s.toString();
} public void setRoleIdsStr(String roleIdsStr) {
if(StringUtils.isEmpty(roleIdsStr)) {
return;
}
String[] roleIdStrs = roleIdsStr.split(",");
for(String roleIdStr : roleIdStrs) {
if(StringUtils.isEmpty(roleIdStr)) {
continue;
}
getRoleIds().add(Long.valueOf(roleIdStr));
}
} @Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false; User user = (User) o; if (id != null ? !id.equals(user.id) : user.id != null) return false; return true;
} @Override
public int hashCode() {
return id != null ? id.hashCode() : 0;
} @Override
public String toString() {
return "User{" +
"id=" + id +
", organizationId=" + organizationId +
", username='" + username + '\'' +
", password='" + password + '\'' +
", salt='" + salt + '\'' +
", roleIds=" + roleIds +
", locked=" + locked +
'}';
}
}

User

这都是前面章节的内容了。重点是UserRunAs。该实体定义了授予身份账号(A)与被授予身份账号(B)的关系。B将假装为A进行访问。

 package com.github.zhangkaitao.shiro.chapter21.entity;

 import java.io.Serializable;

 public class UserRunAs implements Serializable {
private Long fromUserId;//授予身份帐号
private Long toUserId;//被授予身份帐号

//getter、setter略 @Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false; UserRunAs userRunAs = (UserRunAs) o; if (fromUserId != null ? !fromUserId.equals(userRunAs.fromUserId) : userRunAs.fromUserId != null) return false;
if (toUserId != null ? !toUserId.equals(userRunAs.toUserId) : userRunAs.toUserId != null) return false; return true;
} @Override
public int hashCode() {
int result = fromUserId != null ? fromUserId.hashCode() : 0;
result = 31 * result + (toUserId != null ? toUserId.hashCode() : 0);
return result;
} @Override
public String toString() {
return "UserRunAs{" +
"fromUserId=" + fromUserId +
", toUserId=" + toUserId +
'}';
}
}

4.Service层

其他的就只放接口类了,runas相关的会放上实现类。

 package com.github.zhangkaitao.shiro.chapter21.service;

 import com.github.zhangkaitao.shiro.chapter21.entity.Organization;
import java.util.List; public interface OrganizationService { public Organization createOrganization(Organization organization);
public Organization updateOrganization(Organization organization);
public void deleteOrganization(Long organizationId); Organization findOne(Long organizationId);
List<Organization> findAll(); Object findAllWithExclude(Organization excludeOraganization); void move(Organization source, Organization target);
}

OrganizationService

 package com.github.zhangkaitao.shiro.chapter21.service;

 import com.github.zhangkaitao.shiro.chapter21.entity.Resource;
import java.util.List;
import java.util.Set; public interface ResourceService { public Resource createResource(Resource resource);
public Resource updateResource(Resource resource);
public void deleteResource(Long resourceId); Resource findOne(Long resourceId);
List<Resource> findAll(); /**
* 得到资源对应的权限字符串
* @param resourceIds
* @return
*/
Set<String> findPermissions(Set<Long> resourceIds); /**
* 根据用户权限得到菜单
* @param permissions
* @return
*/
List<Resource> findMenus(Set<String> permissions);
}

ResourceService

 package com.github.zhangkaitao.shiro.chapter21.service;

 import com.github.zhangkaitao.shiro.chapter21.entity.Role;
import java.util.List;
import java.util.Set; public interface RoleService { public Role createRole(Role role);
public Role updateRole(Role role);
public void deleteRole(Long roleId); public Role findOne(Long roleId);
public List<Role> findAll(); /**
* 根据角色编号得到角色标识符列表
* @param roleIds
* @return
*/
Set<String> findRoles(Long... roleIds); /**
* 根据角色编号得到权限字符串列表
* @param roleIds
* @return
*/
Set<String> findPermissions(Long[] roleIds);
}

RoleService

 package com.github.zhangkaitao.shiro.chapter21.service;

 import com.github.zhangkaitao.shiro.chapter21.entity.User;
import java.util.List;
import java.util.Set; public interface UserService { public User createUser(User user);
public User updateUser(User user);
public void deleteUser(Long userId); public void changePassword(Long userId, String newPassword); User findOne(Long userId);
List<User> findAll();
public User findByUsername(String username); /**
* 根据用户名查找其角色
* @param username
* @return
*/
public Set<String> findRoles(String username); /**
* 根据用户名查找其权限
* @param username
* @return
*/
public Set<String> findPermissions(String username); }

UserService

RunAsService:

 package com.github.zhangkaitao.shiro.chapter21.service;
import java.util.List; public interface UserRunAsService { public void grantRunAs(Long fromUserId, Long toUserId);//授予身份
public void revokeRunAs(Long fromUserId, Long toUserId);//回收身份

public boolean exists(Long fromUserId, Long toUserId);//关系存在

public List<Long> findFromUserIds(Long toUserId);//查找
public List<Long> findToUserIds(Long fromUserId);//查找

}

UserRunAsServiceImpl:

 package com.github.zhangkaitao.shiro.chapter21.service;

 import com.github.zhangkaitao.shiro.chapter21.dao.UserRunAsDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List; @Service
public class UserRunAsServiceImpl implements UserRunAsService {
@Autowired
private UserRunAsDao userRunAsDao;

@Override
public void grantRunAs(Long fromUserId, Long toUserId) {
userRunAsDao.grantRunAs(fromUserId, toUserId);
} @Override
public void revokeRunAs(Long fromUserId, Long toUserId) {
userRunAsDao.revokeRunAs(fromUserId, toUserId);
} @Override
public boolean exists(Long fromUserId, Long toUserId) {
return userRunAsDao.exists(fromUserId, toUserId);
} @Override
public List<Long> findFromUserIds(Long toUserId) {
return userRunAsDao.findFromUserIds(toUserId);
} @Override
public List<Long> findToUserIds(Long fromUserId) {
return userRunAsDao.findToUserIds(fromUserId);
}
}

5.Dao层

同样,其他的几个就只放接口了。

 package com.github.zhangkaitao.shiro.chapter21.dao;

 import com.github.zhangkaitao.shiro.chapter21.entity.Organization;
import java.util.List; public interface OrganizationDao { public Organization createOrganization(Organization organization);
public Organization updateOrganization(Organization organization);
public void deleteOrganization(Long organizationId); Organization findOne(Long organizationId);
List<Organization> findAll(); List<Organization> findAllWithExclude(Organization excludeOraganization); void move(Organization source, Organization target);
}

OrganizationDao

 package com.github.zhangkaitao.shiro.chapter21.dao;

 import com.github.zhangkaitao.shiro.chapter21.entity.Resource;
import java.util.List; public interface ResourceDao { public Resource createResource(Resource resource);
public Resource updateResource(Resource resource);
public void deleteResource(Long resourceId); Resource findOne(Long resourceId);
List<Resource> findAll(); }

ResourceDao

 package com.github.zhangkaitao.shiro.chapter21.dao;

 import com.github.zhangkaitao.shiro.chapter21.entity.Role;
import java.util.List; public interface RoleDao { public Role createRole(Role role);
public Role updateRole(Role role);
public void deleteRole(Long roleId); public Role findOne(Long roleId);
public List<Role> findAll();
}

RoleDao

 package com.github.zhangkaitao.shiro.chapter21.dao;

 import com.github.zhangkaitao.shiro.chapter21.entity.User;
import java.util.List; public interface UserDao { public User createUser(User user);
public User updateUser(User user);
public void deleteUser(Long userId); User findOne(Long userId);
List<User> findAll();
User findByUsername(String username); }

UserDao

UserRunAsDao:

 package com.github.zhangkaitao.shiro.chapter21.dao;

 import java.util.List;

 public interface UserRunAsDao {

     public void grantRunAs(Long fromUserId, Long toUserId);
public void revokeRunAs(Long fromUserId, Long toUserId); public boolean exists(Long fromUserId, Long toUserId); public List<Long> findFromUserIds(Long toUserId);
public List<Long> findToUserIds(Long fromUserId); }

UserRunAsDaoImpl:

 package com.github.zhangkaitao.shiro.chapter21.dao;

 import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;
import java.util.List; @Repository
public class UserRunAsDaoImpl implements UserRunAsDao { @Autowired
private JdbcTemplate jdbcTemplate;

@Override
public void grantRunAs(Long fromUserId, Long toUserId) {
String sql = "insert into sys_user_runas(from_user_id, to_user_id) values (?,?)";
if(!exists(fromUserId, toUserId)) {
jdbcTemplate.update(sql, fromUserId, toUserId);
}
} public boolean exists(Long fromUserId, Long toUserId) {
String sql = "select count(1) from sys_user_runas where from_user_id=? and to_user_id=?";
return jdbcTemplate.queryForObject(sql, Integer.class, fromUserId, toUserId) != 0;
} @Override
public void revokeRunAs(Long fromUserId, Long toUserId) {
String sql = "delete from sys_user_runas where from_user_id=? and to_user_id=?";
jdbcTemplate.update(sql, fromUserId, toUserId);
} @Override
public List<Long> findFromUserIds(Long toUserId) {
String sql = "select from_user_id from sys_user_runas where to_user_id=?";
return jdbcTemplate.queryForList(sql, Long.class, toUserId);
} @Override
public List<Long> findToUserIds(Long fromUserId) {
String sql = "select to_user_id from sys_user_runas where from_user_id=?";
return jdbcTemplate.queryForList(sql, Long.class, fromUserId);
}
}

6.Realm

 package com.github.zhangkaitao.shiro.chapter21.realm;

 import com.github.zhangkaitao.shiro.chapter21.entity.User;
import com.github.zhangkaitao.shiro.chapter21.service.UserService;
import org.apache.shiro.authc.*;
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.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired; public class UserRealm extends AuthorizingRealm { @Autowired
private UserService userService; @Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
String username = (String)principals.getPrimaryPrincipal(); SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
authorizationInfo.setRoles(userService.findRoles(username));
authorizationInfo.setStringPermissions(userService.findPermissions(username));
return authorizationInfo;
} @Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String username = (String)token.getPrincipal(); User user = userService.findByUsername(username); if(user == null) {
throw new UnknownAccountException();//没找到帐号
} if(Boolean.TRUE.equals(user.getLocked())) {
throw new LockedAccountException(); //帐号锁定
} //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配,如果觉得人家的不好可以自定义实现
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
user.getUsername(), //用户名
user.getPassword(), //密码
ByteSource.Util.bytes(user.getCredentialsSalt()),//salt=username+salt
getName() //realm name
);
return authenticationInfo;
} @Override
public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
super.clearCachedAuthorizationInfo(principals);
} @Override
public void clearCachedAuthenticationInfo(PrincipalCollection principals) {
super.clearCachedAuthenticationInfo(principals);
} @Override
public void clearCache(PrincipalCollection principals) {
super.clearCache(principals);
} public void clearAllCachedAuthorizationInfo() {
getAuthorizationCache().clear();
} public void clearAllCachedAuthenticationInfo() {
getAuthenticationCache().clear();
} public void clearAllCache() {
clearAllCachedAuthenticationInfo();
clearAllCachedAuthorizationInfo();
} }

UserRealm

 package com.github.zhangkaitao.shiro.chapter21.credentials;

 import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import java.util.concurrent.atomic.AtomicInteger; public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher { private Cache<String, AtomicInteger> passwordRetryCache; public RetryLimitHashedCredentialsMatcher(CacheManager cacheManager) {
passwordRetryCache = cacheManager.getCache("passwordRetryCache");
} @Override
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
String username = (String)token.getPrincipal();
//retry count + 1
AtomicInteger retryCount = passwordRetryCache.get(username);
if(retryCount == null) {
retryCount = new AtomicInteger(0);
passwordRetryCache.put(username, retryCount);
}
if(retryCount.incrementAndGet() > 5) {
//if retry count > 5 throw
throw new ExcessiveAttemptsException();
} boolean matches = super.doCredentialsMatch(token, info);
if(matches) {
//clear retry count
passwordRetryCache.remove(username);
}
return matches;
}
}

RetryLimitHashedCredentialsMatcher

7.配置文件

略。

8.其他类

略。

由上可知,添加的东西有:

 table:sys_user_runas
entity:UserRunAs
service:UserRunAsService、UserRunAsServiceImpl
dao:UserRunAsDao、UserRunAsDaoImpl

有daoImpl中的代码可知,它只是处理表sys_user_runas的一些基本增删改查操作。那么究竟是如何实现B可以嫁接A的身份进行呢?

请看:2017.2.15 开涛shiro教程-第二十一章-授予身份与切换身份(二) controller

2017.2.15 开涛shiro教程-第二十一章-授予身份与切换身份(一) table、entity、service、dao的更多相关文章

  1. 2017.2.15 开涛shiro教程-第二十一章-授予身份与切换身份(二) controller

    原博客地址:http://jinnianshilongnian.iteye.com/blog/2018398 根据下载的pdf学习. 开涛shiro教程-第二十一章-授予身份与切换身份(二) 1.回顾 ...

  2. 2017.2.16 开涛shiro教程-第十七章-OAuth2集成(一)服务器端

    原博客地址:http://jinnianshilongnian.iteye.com/blog/2018398 根据下载的pdf学习. 开涛shiro教程-第十七章-OAuth2集成 1.OAuth2介 ...

  3. 2017.2.12 开涛shiro教程-第七章-与Web集成

    2017.2.9 开涛shiro教程-第七章-与Web集成(一) 原博客地址:http://jinnianshilongnian.iteye.com/blog/2018398 根据下载的pdf学习. ...

  4. 2017.2.16 开涛shiro教程-第十七章-OAuth2集成(二)客户端

    原博客地址:http://jinnianshilongnian.iteye.com/blog/2018398 根据下载的pdf学习. 开涛shiro教程-第十七章-OAuth2集成 3.客户端 客户端 ...

  5. 2017.2.7 开涛shiro教程-第六章-Realm及相关对象(四)

    原博客地址:http://jinnianshilongnian.iteye.com/blog/2018398 根据下载的pdf学习. 第六章 Realm及相关对象(四) 1.Subject的代码结构 ...

  6. 2017.2.7 开涛shiro教程-第六章-Realm及相关对象(二)

    原博客地址:http://jinnianshilongnian.iteye.com/blog/2018398 根据下载的pdf学习. 第六章 Realm及相关对象(二) 1.Authenticatio ...

  7. 2017.2.7 开涛shiro教程-第六章-Realm及相关对象(一)

    原博客地址:http://jinnianshilongnian.iteye.com/blog/2018398 根据下载的pdf学习. 第六章 Realm及相关对象 1.用户.角色.权限的关系 用户和角 ...

  8. 2017.2.7 开涛shiro教程-第六章-Realm及相关对象(三)

    原博客地址:http://jinnianshilongnian.iteye.com/blog/2018398 根据下载的pdf学习. 第六章 Realm及相关对象(三) 1.准备3个Realm MyR ...

  9. 2017.4.12 开涛shiro教程-第十八章-并发登录人数控制

    原博客地址:http://jinnianshilongnian.iteye.com/blog/2018398 根据下载的pdf学习. 开涛shiro教程-第十八章-并发登录人数控制 shiro中没有提 ...

随机推荐

  1. python 打印9*9乘法表

    # -*- coding: utf8 -*- # Author:wxq 1. for i in range(1,10): for j in range(1,i+1): print "%d*% ...

  2. 动态规划--找零钱 coin change

    来自http://www.geeksforgeeks.org/dynamic-programming-set-7-coin-change/ 对于整数N,找出N的所有零钱的表示.零钱可以用S={s1,s ...

  3. sqlserver创建存储过程返回table

    --创建存储过程test create procedure [dbo].[test] ( @I_MTR NVARCHAR (MAX), @I_TYPE NVARCHAR (MAX), @I_FAC N ...

  4. BZOJ 1057:[ZJOI2007]棋盘制作(最大01子矩阵+奇偶性)

    [ZJOI2007]棋盘制作                                          时间限制: 20 Sec 内存限制: 162 MB[题目描述]国际象棋是世界上最古老的博 ...

  5. 【Luogu】P4172水管局长(LCT)

    题目链接 有个结论是x到y的路径上最长边权值等于最小生成树上最长边权值,于是问题转化为最小生成树. 再考虑把问题反过来,删边变成加边. 于是变成动态维护最小生成树,LCT可以做到. #include& ...

  6. 树的合并 connect

    树的合并 connect 题目描述 话说moreD经过不懈努力,终于背完了循环整数,也终于完成了他的蛋糕大餐. 但是不幸的是,moreD得到了诅咒,受到诅咒的原因至今无人知晓. moreD在发觉自己得 ...

  7. javasript深度拷贝

    1 将json数据转换为字符串形式 var j={"name":"daenerys targaryen","dragon":"{& ...

  8. The type or namespace name 'Html' does not exist in the namespace 'System.Web.Mvc' (are you missing an assembly reference?)

    The type or namespace name 'Html' does not exist in the namespace 'System.Web.Mvc' (are you missing ...

  9. IIC知识

    任何一个微处理器都要与一定数量的部件和外围设备连接,但如果将各部件和每一种外围设备都分别用一组线路与CPU直接连接,那么连线将会错综复杂,甚至难以实现.为了简化硬件电路设计.简化系统结构,常用一组线路 ...

  10. python 代码格式

    python 代码格式 Python对代码的缩进要求非常严格,如果不采用合理的代码缩进,将抛出SyntaxError异常 Python语句中一般以新行作为为语句的结束符.但是我们可以使用斜杠( )将一 ...