为什么增加字段?

使用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步操作后,就完成了扩展字段的配置。