为什么增加字段?
使用shiro框架后,想必会用到获取当前用户信息进行相关的逻辑操作,如下图:
/**
* 获取当前登录用户
*/
protected LoginUserInfo getLoginUser () {
return (LoginUserInfo)SecurityUtils.getSubject().getPrincipal();
}
如果不进行相关用户信息配置,获取到的用户信息字段可能就个别几个,满足不了开发者的需求,接下来介绍如何在shiro框架基础上,扩展用户信息增加额外的字段。
1.定义需要的用户信息类
@Data
public class LoginUserInfo implements Serializable{
private static final long serialVersionUID = 271062433005933909L;
private Long id;
private String username;
private String realname;
private String avatar;
private Date birthday;
private String sex;
private List<String> roles;
private List<String> permissions;
private Long schoolId;
private Long collegeId;
@JsonIgnore
private String password;
@JsonIgnore
private String salt;
/**
* 将用户实体转为登录用户信息
*
* @param user 用户实体
* @param roles 角色列表
* @param permissions 权限列表
* @return LoginUserInfo
*/
public static LoginUserInfo from(SystemUser user, List<SystemRole> roles, List<SystemPermission> permissions) {
if (user == null) {
return null;
}
// 拷贝用户信息
LoginUserInfo loginUserInfo = new LoginUserInfo();
BeanUtils.copyProperties(user, loginUserInfo);
// 设置角色信息
List<String> rs = new ArrayList<>();
for (SystemRole role : roles) {
rs.add(role.getCode());
}
loginUserInfo.setRoles(rs);
// 设置权限信息
List<String> pms = new ArrayList<>();
for (SystemPermission permission : permissions) {
pms.add(permission.getCode());
}
loginUserInfo.setPermissions(pms);
return loginUserInfo;
}
}
2.在自定义ShiroRealm中doGetAuthenticationInfo方法进行操作
/**
* 认证处理
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
// 获取用户名
String username = authenticationToken.getPrincipal().toString();
final Set<Object> keys = shiroCache.keys("shiro:session:*");
if (CollUtil.isNotEmpty(keys)) {
keys.forEach(k -> {
try {
if (ObjectUtil.isNotNull(k)) {
Session v = (Session)redisTemplate.opsForValue().get(k);
log.debug("shiro-session-k={}, shiro-session-v={}", k.toString(), v.toString());
SimplePrincipalCollection attribute = (SimplePrincipalCollection)v.getAttribute("org.apache.shiro.subject.support.DefaultSubjectContext_PRINCIPALS_SESSION_KEY");
LoginUserInfo primaryPrincipal = (LoginUserInfo)attribute.getPrimaryPrincipal();
if (ObjectUtil.isNotNull(v) && v instanceof Session) {
log.debug("shiro-session-k={}, shiro-session-v={}", k.toString(), ((Session) v).toString());
}
}
} catch (Exception e) {
log.error(e.getMessage());
}
});
}
// 根据用户名查询用户对象
SystemUser queryDto = new SystemUser();
queryDto.setUsername(username);
queryDto.setDeleted(Boolean.FALSE);
queryDto.setStatus(StatusEnum.PASS);
SystemUser user = systemUserService.findOne(queryDto);
if (user == null) {
return null;
}
// 获取登录用户信息
List<SystemRole> roles = systemRoleService.findByUserId(user.getId());
List<SystemPermission> permissions = systemPermissionService.findByUserId(user.getId());
LoginUserInfo userInfo = LoginUserInfo.from(user, roles, permissions);
// 验证用户
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(userInfo, user.getPassword(), this.getName());
return simpleAuthenticationInfo;
}
注意上方代码里面的业务处理,获取用户信息。
SystemUser user = systemUserService.findOne(queryDto);
把用户信息转储到刚刚定义的LoginUserInfo用户信息类。
LoginUserInfo userInfo = LoginUserInfo.from(user, roles, permissions);
把用户信息存入shiro中,关键一步。
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(userInfo, user.getPassword(), this.getName());
完成上述2步操作后,就完成了扩展字段的配置。