我是靠谱客的博主 辛勤毛巾,最近开发中收集的这篇文章主要介绍SpringBoot整合shiro同时解决注解权限不生效(附源码)1.数据库表设计2.实体:3.查询当前登陆用户方法,获取所有角色,所有权限4.pom配置5.shiroConfig配置6.配置自己的  realm7.方法上加权限8,运行效果9.源码地址:,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

1.shiro apache出品的很好用的权限框架,理论上来说只需要程序员配置两个类,shiro就能为我们工作起来。

这几天研究shiro,集成到springboot中,并使用注解权限,踩了不少坑,希望这篇文章能够帮助到大家

本文我将讲述一下springboot整合shiro,使用 @RequiresPermissions 进行控制器权限控制

1.数据库表设计

具体sql文件以及初始化数据在这里:https://github.com/winterme/pkusoft/blob/master/src/sql/user_center.sql

DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user` (
  `uid` varchar(36) NOT NULL,
  `username` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  `password_salt` varchar(255) DEFAULT NULL,
  `status` varchar(255) DEFAULT NULL,
  `create_user` varchar(255) DEFAULT NULL,
  `create_uid` varchar(36) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`uid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `sys_role_permission`;
CREATE TABLE `sys_role_permission` (
  `rid` varchar(36) DEFAULT NULL,
  `pid` varchar(36) DEFAULT NULL,
  `role_name` varchar(255) DEFAULT NULL,
  `create_user` varchar(255) DEFAULT NULL,
  `create_uid` varchar(36) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `sys_user_role`;
CREATE TABLE `sys_user_role` (
  `id` varchar(36) NOT NULL,
  `uid` varchar(36) NOT NULL,
  `rid` varchar(36) NOT NULL,
  `create_user` varchar(255) DEFAULT NULL,
  `create_uid` varchar(36) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `sys_permission`;
CREATE TABLE `sys_permission` (
  `pid` varchar(36) NOT NULL,
  `permission_name` varchar(255) DEFAULT NULL,
  `permission` varchar(255) DEFAULT NULL,
  `url` varchar(255) DEFAULT NULL,
  `create_user` varchar(255) DEFAULT NULL,
  `create_uid` varchar(36) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`pid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

2.实体:

在user里面放入 roles和permisssion 两个属性,用来查询user 的时候手动关联查出 该用户的角色和权限

@Table(name = "sys_user")
public class SysUser {
    @Id
    private String uid;

    private String username;

    private String password;

    @Column(name = "password_salt")
    private String passwordSalt;

    // 所有的角色
    private List<String> roles;

    // 所有的权限
    private List<String> permission;

    private String status;

    @Column(name = "create_user")
    private String createUser;

    @Column(name = "create_uid")
    private String createUid;

    @Column(name = "create_time")
    private Date createTime;

    .....getset

3.查询当前登陆用户方法,获取所有角色,所有权限

@Override
    public SysUser getUserByUserNameWithPermission(String username) {
        // 用户名唯一,此处用用户名查出当前用户
        Example example = new Example(SysUser.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("username",username);
        List<SysUser> lists = sysUserMapper.selectByExample(example);
        if( lists.size()==0 ){
            return null;
        }

        SysUser sysUser = lists.get(0);
        // 查出所有的角色名
        List<SysRolePermission> roles = sysRolePermissionMapper.getRoleNameByUserId(sysUser.getUid());
        // 查出所有的权限
        List<SysPermission> permissions = sysPermissionMapper.getSysPermissionByUid(sysUser.getUid());

        // roleName
        List<String> rolesName = new ArrayList<>();
        for (SysRolePermission role : roles ) {
            rolesName.add( role.getRoleName() );
        }
        sysUser.setRoles( rolesName );

        // permissions
        List<String> permissionsByUser = new ArrayList<>();
        for (SysPermission p  : permissions) {
            permissionsByUser.add( p.getPermission() );
        }
        sysUser.setPermission( permissionsByUser );

        return sysUser;
    }

4.pom配置

        <!-- shiro 相关包 -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>${shiro.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>${shiro.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <version>${shiro.version}</version>
        </dependency>
        <!-- End  -->

此处的  ${shiro.version} 使用 1.4.0 版本

5.shiroConfig配置

注意看代码上的注释

/**
 * shiro 配置
 */
@Configuration
public class ShiroConfig {

    private final static Logger logger = LoggerFactory.getLogger(ShiroConfig.class);

    // 下面两个方法对 注解权限起作用有很大的关系,请把这两个方法,放在配置的最上面
    @Bean(name = "lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }
    @Bean
    public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator autoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        autoProxyCreator.setProxyTargetClass(true);
        return autoProxyCreator;
    }

    //将自己的验证方式加入容器
    @Bean
    public MyRealm myRealm() {
        System.out.println( "注入 realm" );
        MyRealm myRealm = new MyRealm();
        return myRealm;
    }

    //配置shiro session 的一个管理器
    @Bean(name = "sessionManager")
    public DefaultWebSessionManager getDefaultWebSessionManager(){
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        // 设置session过期时间
        sessionManager.setGlobalSessionTimeout(60*60*1000);
        return sessionManager;
    }

    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager() {
        DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
        defaultWebSecurityManager.setRealm( myRealm() );
        //defaultWebSecurityManager.setSessionManager( getDefaultWebSessionManager() );
        return defaultWebSecurityManager;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(
            DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }

    //Filter工厂,设置对应的过滤条件和跳转条件
    @Bean
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
        System.out.println( "shiro 过滤器" );
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);

        //拦截器.
        Map<String,String> filterChainDefinitionMap = new LinkedHashMap<String,String>();

        // 配置不会被拦截的链接 顺序判断
        filterChainDefinitionMap.put("/static/**", "anon");
        filterChainDefinitionMap.put("/login", "anon");
        //配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了
        filterChainDefinitionMap.put("/logout", "logout");
        //<!-- 过滤链定义,从上向下顺序执行,一般将/**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
        //<!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
        filterChainDefinitionMap.put("/**", "authc");
        // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
        shiroFilterFactoryBean.setLoginUrl("/login.html");
        // 登录成功后要跳转的链接
        shiroFilterFactoryBean.setSuccessUrl("/index.html");

        //未授权界面;
        shiroFilterFactoryBean.setUnauthorizedUrl("/403.html");
        shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilterFactoryBean;
    }

}

6.配置自己的  realm

/**
 * 自定义 realm
 */
public class MyRealm extends AuthorizingRealm {

    @Autowired
    private SysUserService sysUserService;

    @Override
    public String getName() {
        return "myRealm";
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        // 从session中获取 user 对象
        Session session = SecurityUtils.getSubject().getSession();
        SysUser user = (SysUser)session.getAttribute("USER_SESSION");
        System.out.println( "执行了================>" );
        // 权限信息对象
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addRoles( user.getRoles() );
        info.addStringPermissions( user.getPermission() );

        Set<String> roles = info.getRoles();
        for (String str  : roles) {
            System.out.println( "角色:"+ str );
        }
        Set<String> permissions = info.getStringPermissions();
        for (String str  : permissions) {
            System.out.println( "权限:"+ str );
        }


        return info;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //加这一步的目的是在Post请求的时候会先进认证,然后在到请求
        if (authenticationToken.getPrincipal() == null) {
            return null;
        }
        String username = (String)authenticationToken.getPrincipal();
        String password = new String((char[])authenticationToken.getCredentials());
        System.out.println( "username="+username+",password="+password );

        // 获取用户名。通过 username 找到该用户
        SysUser user = sysUserService.getUserByUserNameWithPermission(username);
        if( !"1".equals(user.getStatus()) ){
            throw new LockedAccountException();
        }

        // 从数据库查询出来的用户名密码,进行验证
        // 用户名,密码,密码盐值,realm 名称
        // 登陆的时候直接调用 subject.login() 即可自动调用该方法
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(
                authenticationToken.getPrincipal() , user.getPassword() , getName()
        );

        Session session = SecurityUtils.getSubject().getSession();
        session.setAttribute("USER_SESSION", user);
        return info;
    }
}

7.方法上加权限

    @RequestMapping("/licm/getMsgById/{id}")
    @ResponseBody
    @RequiresPermissions(value = {"msg:find"})
    public JsonResult getMsgById(@PathVariable("id")String id){
        try {
            Msg msg = msgService.selectMsgById(id);
            return new JsonResult(true,msg);
        } catch (Exception e) {
            logger.error("查询失败!");
            return new JsonResult(false,"");
        }
    }

    @RequestMapping("/licm/getMsgByPage/{start}/{size}")
    @ResponseBody
    @RequiresPermissions(value = {"msg:list"})
    public JsonResult getMsgById(@PathVariable("start")int start,@PathVariable("size")int size){
        try {
            Map<String , Object> result = msgService.selectListMsgByPage(start,size);
            return new JsonResult(true, result);
        } catch (Exception e) {
            logger.error("查询失败!");
            return new JsonResult(false,"");
        }
    }

8,运行效果

9.源码地址:

https://github.com/winterme/pkusoft/

最后

以上就是辛勤毛巾为你收集整理的SpringBoot整合shiro同时解决注解权限不生效(附源码)1.数据库表设计2.实体:3.查询当前登陆用户方法,获取所有角色,所有权限4.pom配置5.shiroConfig配置6.配置自己的  realm7.方法上加权限8,运行效果9.源码地址:的全部内容,希望文章能够帮你解决SpringBoot整合shiro同时解决注解权限不生效(附源码)1.数据库表设计2.实体:3.查询当前登陆用户方法,获取所有角色,所有权限4.pom配置5.shiroConfig配置6.配置自己的  realm7.方法上加权限8,运行效果9.源码地址:所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(60)

评论列表共有 0 条评论

立即
投稿
返回
顶部