springboot中接入shiro权限框架

首先在pom.xml中引入shiro包

<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-spring</artifactId>
			<version>1.5.3</version>
		</dependency>

下面是表和实体类结构:

注:继承的baseBean为我的基础实体类,包含主键,操作记录等信息,根据业务逻辑自行修改

一、用户表实体类

@org.hibernate.annotations.Table(appliesTo = "pc_user", comment = "Pc端用户表")
public class PcUser extends BaseBean {
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(columnDefinition = "varchar(100) COMMENT 'pc用户编号'")
    private String pcUserId;
    @Column(columnDefinition = "varchar(100) COMMENT '用户名'")
    private String userName;
    @Column(columnDefinition = "varchar(100) COMMENT '密码'")
    private String passWord;
    @GeneratedValue(generator="system-uuid")
    @GenericGenerator(name="system-uuid", strategy = "uuid")
    @Column(columnDefinition = "varchar(100) COMMENT '加盐'")
    private String salt;
    @Column(columnDefinition = "datetime COMMENT '最后登录时间'")
    private Date lastLoginTime;
}

此为自动建表实体类,业务逻辑中使用时增加PcUserVO进行逻辑处理

@Data
public class PcUserVO extends BaseBean {
    private String pcUserId;
    private String userName;
    private String passWord;
    private String salt;
    private Date lastLoginTime;
    /**
     * 用户对应的角色集合
     */
    private Set<RoleVO> roles;
}

二、角色表实体类

@org.hibernate.annotations.Table(appliesTo = "role", comment = "pc端角色表")
public class Role extends BaseBean {
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(columnDefinition = "varchar(100) COMMENT '角色编号'")
    private String roleId;
    @Column(columnDefinition = "varchar(100) COMMENT '角色名称'")
    private String roleName;
    @Column(columnDefinition = "varchar(100) COMMENT '角色描述'")
    private String description;
}

此为自动建表实体类,业务逻辑中使用时增加RoleVO 进行逻辑处理

import com.pcframe.entity.BaseBean;
import com.pcframe.entity.Permissions;
import lombok.Data;
import java.util.Set;

@Data
public class RoleVO extends BaseBean {
    private String roleId;
    private String roleName;
    private String description;
    /**
     * 角色对应权限集合
     */
    private Set<Permissions> permissions;
}

三、权限表实体类

@org.hibernate.annotations.Table(appliesTo = "permissions", comment = "pc端权限表")
public class Permissions extends BaseBean {
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(columnDefinition = "varchar(100) COMMENT '权限编号'")
    private String permissionsId;
    @Column(columnDefinition = "varchar(250) COMMENT '权限名称'")
    private String permissionsName;
    @Column(columnDefinition = "varchar(100) COMMENT '权限描述'")
    private String description;

}

四、用户角色关系表实体类

@org.hibernate.annotations.Table(appliesTo = "pc_user_link_role", comment = "用户角色关系表 ")
public class PcUserLinkRole extends BaseBean {
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(columnDefinition = "varchar(100) COMMENT 'pc用户编号'")
    private String pcUserId;
    @Column(columnDefinition = "varchar(100) COMMENT '角色编号'")
    private String roleId;
}

五、角色权限关系表实体类

@org.hibernate.annotations.Table(appliesTo = "role_link_permissions", comment = "角色权限关系表 ")
public class RoleLinkPermissions extends BaseBean  {
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(columnDefinition = "varchar(100) COMMENT '角色编号'")
    private String roleId;
    @Column(columnDefinition = "varchar(100) COMMENT '权限编号'")
    private String permissionsId;
}

下面是数据库查询角色与权限的服务实现类:

六、PcUserLoginServiceImpl

package com.pcframe.service.impl;

import com.pcframe.VO.PcUserVO;
import com.pcframe.VO.RoleVO;
import com.pcframe.entity.PcUser;
import com.pcframe.entity.Permissions;
import com.pcframe.entity.Role;
import com.pcframe.service.PcUserLoginService;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

@Service
public class PcUserLoginServiceImpl implements PcUserLoginService {

    @Override
    public PcUserVO getUserByName(String getMapByName) {
        return getMapByName(getMapByName);
    }

    /**
     * 模拟数据库查询(根据实际业务进行修改即可)
     *
     * @param userName 用户名
     * @return PcUserVO 
     */
    private PcUserVO getMapByName(String userName) {
        Permissions permissions1 = new Permissions();
        permissions1.setId(1L);
        permissions1.setPermissionsName("abc");
        Permissions permissions2 = new Permissions();
        permissions2.setId(2L);
        permissions2.setPermissionsName("abcd");
        Set<Permissions> permissionsSet = new HashSet<>();
        permissionsSet.add(permissions1);
        permissionsSet.add(permissions2);
        RoleVO role = new RoleVO();
        role.setId(1L);
        role.setRoleName("admin");
        role.setPermissions(permissionsSet);
        Set<RoleVO> roleSet = new HashSet<>();
        roleSet.add(role);
        PcUserVO user = new PcUserVO();
        user.setId(1L);
        user.setUserName("zyx");
        user.setPassWord("123456");
        user.setRoles(roleSet);
        Map<String, PcUserVO> map = new HashMap<>();
        map.put(user.getUserName(), user);

        Set<Permissions> permissionsSet1 = new HashSet<>();
        permissionsSet1.add(permissions1);
        RoleVO role1 = new RoleVO();
        role1.setId(2L);
        role1.setRoleName("user");
        role1.setPermissions(permissionsSet1);
        Set<RoleVO> roleSet1 = new HashSet<>();
        roleSet1.add(role1);
        PcUserVO user1 = new PcUserVO();
        user1.setId(2L);
        user1.setUserName("ccc");
        user1.setPassWord("123456");
        user1.setRoles(roleSet1);
        map.put(user1.getUserName(), user1);
        return map.get(userName);
    }
}

自定义Realm用于查询用户的角色和权限信息并保存到权限管理器:

七、PcUserRealm

package com.pcframe.realm;

import com.pcframe.VO.PcUserVO;
import com.pcframe.VO.RoleVO;
import com.pcframe.entity.PcUser;
import com.pcframe.entity.Permissions;
import com.pcframe.entity.Role;
import com.pcframe.service.PcUserLoginService;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
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;
import org.springframework.util.StringUtils;

public class PcUserRealm extends AuthorizingRealm {

    @Autowired
    private PcUserLoginService pcUserLoginService;

    /**
     * @MethodName doGetAuthorizationInfo
     * @Description 权限配置类
     * @Param [principalCollection]
     * @Return AuthorizationInfo
     * @Author WangShiLin
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //获取登录用户名
        String name = (String) principalCollection.getPrimaryPrincipal();
        //查询用户名称
        PcUserVO pcUser = pcUserLoginService.getUserByName(name);
        //添加角色和权限
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        for (RoleVO role : pcUser.getRoles()) {
            //添加角色
            simpleAuthorizationInfo.addRole(role.getRoleName());
            //添加权限
            for (Permissions permissions : role.getPermissions()) {
                simpleAuthorizationInfo.addStringPermission(permissions.getPermissionsName());
            }
        }
        return simpleAuthorizationInfo;
    }

    /**
     * @MethodName doGetAuthenticationInfo
     * @Description 认证配置类
     * @Param [authenticationToken]
     * @Return AuthenticationInfo
     * @Author WangShiLin
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        if (StringUtils.isEmpty(authenticationToken.getPrincipal())) {
            return null;
        }
        //获取用户信息
        String name = authenticationToken.getPrincipal().toString();
        PcUserVO pcUser = pcUserLoginService.getUserByName(name);
        if (pcUser == null) {
            //这里返回后会报出对应异常
            return null;
        } else {
            //这里验证authenticationToken和simpleAuthenticationInfo的信息
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(name, pcUser.getPassWord().toString(), getName());
            return simpleAuthenticationInfo;
        }
    }
}

八、shiro的核心过滤器ShiroConfig

package com.pcframe.config;
import com.pcframe.realm.PcUserRealm;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

    @Bean
    @ConditionalOnMissingBean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
        defaultAAP.setProxyTargetClass(true);
        return defaultAAP;
    }

    //将自己的验证方式加入容器
    @Bean
    public PcUserRealm myShiroRealm() {
        PcUserRealm pcUserRealm = new PcUserRealm();
        return pcUserRealm;
    }

    //权限管理,配置主要是Realm的管理认证
    @Bean
    public SecurityManager securityManager() {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(myShiroRealm());
        return securityManager;
    }

    //Filter工厂,设置对应的过滤条件和跳转条件
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map<String, String> map = new HashMap<>();
        /**
         * anon 没有参数,表示可以匿名使用。
         * authc 表示需要认证(登录)才能使用,没有参数
         * authcBasic 没有参数表示httpBasic认证
         * logout 表示添加shiro的默认退出
         * noSessionCreation
         * perms 参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,例如/admins/user/**=perms["user:add:*,user:modify:*"],当有多个参数时必须每个参数都通过才通过,想当于isPermitedAll()方法。
         * port port[8091],当请求的url的端口不是8091是跳转到schemal://serverName:8091?url,其中schmal是协议http或https等,serverName是你访问的host,8091是url配置里port的端口,url是你访问的url里的?后面的参数。也就是默认更改端口
         * rest 根据请求的方法,相当于/user/**=perms[user:method] ,其中method为post,get,delete等。
         * roles 参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割,当有多个参数时,例如user/**=roles["admin,guest"],每个参数通过才算通过,相当于hasAllRoles()方法。
         * ssl 没有参数,表示安全的url请求,协议为https
         * user 没有参数表示必须存在用户,当登入操作时不做检查
         */
        //登出
        map.put("/logout", "logout");
        //对所有用户认证
        map.put("/**", "authc");
        //登录(身份认证失败,则跳转到登录页面的配置 没有登录的用户请求需要登录的页面时自动跳转到登录页面,不是必须的属性)
        shiroFilterFactoryBean.setLoginUrl("/login");
        //首页(登录成功默认跳转页面,不配置则跳转至”/”。如果登陆前点击的一个需要登录的页面,则在登录自动跳转到那个需要登录的页面。不跳转到此。)
        shiroFilterFactoryBean.setSuccessUrl("/index");
        //错误页面,认证不通过跳转
        shiroFilterFactoryBean.setUnauthorizedUrl("/403");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
        return shiroFilterFactoryBean;
    }


    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
        authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
        return authorizationAttributeSourceAdvisor;
    }
}

九、Controller进行 测试

package com.pcframe.controller;

import com.pcframe.bean.ResultMessageBean;
import com.pcframe.entity.PcUser;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@Slf4j
public class PcUserController {


    @GetMapping("/login")
    public String login(PcUser pcUser) {
        if (StringUtils.isEmpty(pcUser.getUserName()) || StringUtils.isEmpty(pcUser.getPassWord())) {
            return "请输入用户名和密码!";
        }
        //用户认证信息
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(
                pcUser.getUserName(),
                pcUser.getPassWord()
        );
        try {
            //进行验证,这里可以捕获异常,然后返回对应信息
            subject.login(usernamePasswordToken);
//            subject.checkRole("admin");
//            subject.checkPermissions("query", "add");
        } catch (UnknownAccountException e) {
            log.error("用户名不存在!", e);
            return "用户名不存在!";
        } catch (AuthenticationException e) {
            log.error("密码错误!", e);
            return "密码错误!";
        }
        return "login success";
    }

    @RequiresRoles("admin")
    @GetMapping("/admin")
    public String admin() {
        return "admin success!";
    }

    @RequiresPermissions("abc")
    @GetMapping("/index")
    public String index() {
        return "index success!";
    }

    @RequiresPermissions("abcd")
    @GetMapping("/abcd")
    public String abcd() {
        return "abcd success!";
    }

    @GetMapping("/abcc")
    public String abc() {
        return "abcc success!";
    }


}

十、没有通过权限验证的异常

@ControllerAdvice
@Slf4j
public class MyShiroExceptionHandler {

    @ExceptionHandler
    @ResponseBody
    public String ErrorHandler(AuthorizationException e) {
        log.error("没有通过权限验证!", e);
        return "没有通过权限验证!";
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值