spring boot 前后端分离整合shiro(二)自定义realm

spring boot 前后端分离整合shiro(二)自定义realm

想使用shiro我们需要自定义一个realm,先看看shiro relam的继承关系
在这里插入图片描述
我们关注两个类,一个是AuthenticatingRealm,用来认证;一个是AuthorizingRealm,用来授权。然后AuthorizingRealm又继承了AuthenticatingRealm,所以我们只要继承AuthorizingRealm就既有授权又有认证了。
在这里插入图片描述
继承之后需要实现两个方法,分别用于授权和认证(这两个方法名字很像,不要搞混了),然后就在这两个方法里写我们自己的认证授权。
修改实体类
用户拥有角色,角色拥有权限,而用户又可以直接拥有某个权限,所以给UserInfo添加两个list。顺便序列化,添加序列化id,之后继承redis、配置remenberMe需要。
UserInfo

package com.example.demo.entity;

import lombok.Data;

import java.io.Serializable;
import java.util.List;

@Data
public class UserInfo implements Serializable {

    private static final long serialVersionUID = -482049523211701500L;

    private Integer userId;

    private String userName;

    private String loginName;

    private String password;

    private Integer gender;

    private List<Role> roleList;

    private List<Permission> permissionList;

}

Role

package com.example.demo.entity;

import java.util.List;

public class Role {
    private Integer roleId;

    private String roleName;

    private String description;

    private List<Permission> permissionList;
}

编写UserInfoService

public interface UserInfoService {

    /**
     * 查询用户的基本信息,不包括角色、权限信息
     * @param loginName
     * @return
     */
    UserInfo findUserInfoByLoginName(String loginName);

    /**
     * 查询用户的信息,包括角色、权限信息
     * @param userInfo
     * @return
     */
    UserInfo findUserAllInfoByUserId(UserInfo userInfo);
}

impl

public class UserInfoServiceImpl implements UserInfoService {

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private PermissionMapper permissionMapper;

    @Override
    public UserInfo findUserInfoByLoginName(String loginName) {
        return userInfoMapper.selectUserInfoByLoginName(loginName);
    }

    @Override
    public UserInfo findUserAllInfoByUserId(UserInfo userInfo) {
        userInfo.setRoleList(roleMapper.selectRolesByUserId(userInfo.getUserId()));
        userInfo.setPermissionList(permissionMapper.selectPermissionsByUserId(userInfo.getUserId()));
        return userInfo;
    }
}

部分mapper代码
userInfoMapper

<resultMap id="MyResultMap" type="com.example.demo.entity.UserInfo" >
    <id column="user_id" property="userId" jdbcType="INTEGER" />
    <result column="user_name" property="userName" jdbcType="VARCHAR" />
    <result column="login_name" property="loginName" jdbcType="VARCHAR" />
    <result column="password" property="password" jdbcType="VARCHAR" />
    <result column="status" property="status" jdbcType="INTEGER" />
    <collection property="roleList" ofType="com.example.demo.entity.Role">
      <id column="role_id" property="roleId" jdbcType="INTEGER" />
      <result column="role_name" property="roleName" jdbcType="VARCHAR" />
      <result column="description" property="description" jdbcType="VARCHAR" />
    </collection>
    <collection property="permissionList" ofType="com.example.demo.entity.Permission">
      <id column="pms_id" property="pmsId" jdbcType="INTEGER" />
      <result column="url" property="url" jdbcType="VARCHAR" />
      <result column="pms_name" property="pmsName" jdbcType="VARCHAR" />
    </collection>
  </resultMap>
  
  <select id="selectUserInfoByLoginName" resultMap="MyResultMap">
    select * from user_info u
    where u.login_name = #{loginName};
  </select>

roleMapper

<resultMap id="MyResultMap" type="com.example.demo.entity.Role" >
    <id column="role_id" property="roleId" jdbcType="INTEGER" />
    <result column="role_name" property="roleName" jdbcType="VARCHAR" />
    <result column="description" property="description" jdbcType="VARCHAR" />
    <collection property="permissionList" ofType="com.example.demo.entity.Permission">
      <id column="pms_id" property="pmsId" jdbcType="INTEGER" />
      <result column="url" property="url" jdbcType="VARCHAR" />
      <result column="description" property="description" jdbcType="VARCHAR" />
      <result column="pms_name" property="pmsName" jdbcType="VARCHAR" />
    </collection>
  </resultMap>

  <select id="selectRolesByUserId" resultMap="MyResultMap" parameterType="java.lang.Integer" >
    select r.*, p.*
    from user_role ur
    left join role r on ur.role_id = r.role_id
    left join role_permission rp on r.role_id = rp.role_id
    left join permission p on rp.pms_id = p.pms_id
    where ur.user_id = #{userID};
  </select>

然后完善realm
首先是foGetAuthenticationInfo,认证方法
在这里插入图片描述
关注两个对象,一个是参数 authenticationToken 这个token就是由subject传递过来的用户输入的账号密码,可以从里面拿到loginName。 第二个SimpleAuthenticationInfo对象,代表用户的信息,这里只把查询到的结果返回交给shiro管理,密码比较等操作由shiro去完成。
完整的relam:

package com.example.demo.config;

import com.example.demo.entity.Permission;
import com.example.demo.entity.Role;
import com.example.demo.entity.UserInfo;
import com.example.demo.service.UserInfoService;
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.springframework.beans.factory.annotation.Autowired;

/**
 * @author 黄豪琦
 * 日期:2019-07-09 11:14
 * 说明:
 */
public class CustomizeRealm extends AuthorizingRealm {

    @Autowired
    private UserInfoService userInfoService;

    /**
     * 授权
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //从shiro中拿到保存的对象
        UserInfo var1 = (UserInfo)principalCollection.getPrimaryPrincipal();

        //从数据库中将角色、权限信息查询出
        UserInfo var2 = userInfoService.findUserAllInfoByUserId(var1);

        //保存用户角色、权限信息的对象
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();


        for (Role item: var2.getRoleList()) {
            //添加角色
            info.addRole(item.getRoleName());
            for (Permission pmsItem: item.getPermissionList()) {
                //添加角色所拥有的权限
                info.addStringPermission(pmsItem.getPmsName());
            }
        }

        for (Permission item: var2.getPermissionList()) {
            //添加用户直接拥有的权限
            info.addStringPermission(item.getPmsName());
        }
        return info;
    }

    /**
     * 认证
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

        String loginName = (String)authenticationToken.getPrincipal();
        UserInfo user = userInfoService.findUserInfoByLoginName(loginName);
        if(null == user){
            throw new UnknownAccountException("用户不存在或密码错误");
        }


        return new SimpleAuthenticationInfo(user, user.getPassword(), this.getName());
    }
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值