springboot集成shiro进行权限管理

前言:

由于博客的接口有部分只能由管理员来调用。但如果每个接口都亲自写代码进行权限管理就过于麻烦了,所以引入了shiro这个安全框架,顺带也将原来不规范的密码明文存储在数据库,改为了md5加密。
博客的地址:blog.awakeyoyoyo.com

shiro基本知识

这里略过了,上一篇文章基本带大家入了个门了。

step1

增加4个表来进行角色权限的管理

角色表:
在这里插入图片描述
权限表:
在这里插入图片描述
用户-角色中间表
在这里插入图片描述
角色-权限中间表
在这里插入图片描述
由于仅仅需要用于权限管理,表的设计比较简陋。

step2

修改pom.xml文件新增shiro依赖
<dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-spring</artifactId>
            <version>1.4.0</version>
 </dependency>

step3

新增springboot shiro配置类

主要配置三个shiro重要的bean
1.Realm(用于认证以及授权)
2.DefaultWebSecurityManager(用于管理realm)
3.shiroFilterFactoryBean (用于配置shiro过滤器依赖与安全管理器)
他们之间的关系是由下向上依赖。所以利用spring的注解@Qualifier将其一一对应起来即可。

shiro过滤器的配置规矩

由于其内部实现是用 LinkedHashMap实现,所以我们跟着新建就好
Map<String, String> filterMap = new LinkedHashMap();
anon:无需认真即可访问
authc:必须认证了才可以访问
user:必须拥有记住我功能才能访问
perms:拥有对某个资源的权限才可以访问
role:拥有某个角色权限才可以访问
键值对的形式来进行配置。看下方代码基本可以看懂,我都一一进行了注释。
本来配置了个shiro的密码加密器,但由于本博客的内部结构有些特殊,所以选择自己重写了一个realm来完善。

@Configuration
public class ShiroConfig {
    //shiroFilterFactoryBean:3
    @Bean
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("getDefaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){
        ShiroFilterFactoryBean bean=new ShiroFilterFactoryBean();
        //设置安全管理器
        bean.setUnauthorizedUrl("/toerror");
        bean.setLoginUrl("/tologin");
        bean.setSecurityManager(defaultWebSecurityManager);
        //添加shiro的内置过滤器
        /*
        anon:无需认真即可访问
        authc:必须认证了才可以访问
        user:必须拥有记住我功能才能访问
        perms:拥有对某个资源的权限才可以访问
        role:拥有某个角色权限才可以访问
        */
        Map<String, String> filterMap = new LinkedHashMap();
        filterMap.put("/writeBlog","roles[admin]");
        filterMap.put("/editBlog","roles[admin]");
        filterMap.put("/publishBlog","roles[admin]");
        //授权
        filterMap.put("/**","anon");
        bean.setFilterChainDefinitionMap(filterMap);
        return bean;
    }

    //DefaultWebSecurityManager:2
    @Bean
    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
        DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
        //关联realm
        securityManager.setRealm(userRealm);

        return securityManager;
    }
//    @Bean("hashedCredentialsMatcher")
//    public HashedCredentialsMatcher hashedCredentialsMatcher() {
//        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
//        hashedCredentialsMatcher.setHashAlgorithmName("md5");// 散列算法:这里使用MD5算法;
//        hashedCredentialsMatcher.setHashIterations(2);// 散列的次数,比如散列两次,相当于md5(md5(""));
//        //hashedCredentialsMatcher.setStoredCredentialsHexEncoded(true);// 表示是否存储散列后的密码为16进制,需要和生成密码时的一样,默认是base64;
//        return hashedCredentialsMatcher;
//    }

    @Bean
    public  UserRealm userRealm(){
        UserRealm userRealm=new UserRealm();
//        userRealm.setCredentialsMatcher(matcher);
//        userRealm.setAuthorizationCachingEnabled(true);
        return userRealm;
    }
}
step4
自定义realm

这个挺简单的,基本注释都有,自己看吧。

public class UserRealm extends AuthorizingRealm {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private PermissionMapper permissionMapper;
    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("执行了doGetAuthorizationInfo-----授权");
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        User user=(User) SecurityUtils.getSubject().getPrincipal();
        Set<String> roles=new HashSet<String>();
        List<String> rolesByUserId=roleMapper.getRolesByUserId(user.getId());
        for(String role:rolesByUserId) {
            roles.add(role);
        }
        List<String> permissionsByUserName = permissionMapper.getPermissionsByUserId(user.getId());
        for(String permission:permissionsByUserName) {
            info.addStringPermission(permission);
        }
        info.setRoles(roles);
        return info;
    }
    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
       System.out.println("执行了doGetAuthenticationInfo 认真");
       UsernamePasswordToken userToken=(UsernamePasswordToken)authenticationToken;
       User user=userMapper.selectUserByaccoun_id(userToken.getUsername());
       if (user==null){
           return null;
       }
       String password=String.valueOf(userToken.getPassword());
       if (user.getPassword().equals(password)){
           //通过token验证
           SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(user,user.getPassword(),getName());
           return info;
       }
       //账号密码验证
        String salt = user.getSalt();
//        System.out.println(userToken.getUsername()+"===="+userToken.getPassword().toString());
        String encodedPassword = ShiroMd5Util.shiroEncryption(password,salt);
//        System.out.println("密码:"+encodedPassword);
        userToken.setPassword(encodedPassword.toCharArray());
        SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(user,user.getPassword(),getName());
//        info.setCredentialsSalt(ByteSource.Util.bytes(user.getSalt()));
        return info;
    }
}
总结:

shiro是一个很好用的安全框架,本博客网站用到的只是他的一些基本功能,主要用来对于博客的一些接口进行权限管理,shiro还实现了一个不依赖web容器的session(与绑定subject,而subject又存储与线程上下文),让我们的开发更加方便。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值