Apache Shiro

一、RBAC模型

        RBAC模型(Role-Based Access Control:基于角色的访问控制)

        组成:用户、角色和权限

        RBAC通过定义角色的权限,并对用户授予某个角色从而来控制用户的权限,实现了用户和权限的逻辑分离,最终可以映射以下关系:

  • User(用户):每个用户都有唯一的UID识别,并被授予不同的角色

  • Role(角色):不同角色具有不同的权限

  • Permission(权限):访问权限

  • 用户-角色映射:用户和角色之间的映射关系

  • 角色-权限映射:角色和权限之间的映射

二、Apache Shiro

Java 安全框架 ,它执行身份验证、授权、加密和会话管理

Shiro 提供应用程序安全 API 来执行以下方面(我喜欢将这些称为应用程序安全的 4 个基石):

  • Authentication(认证):用户身份识别,通常被称为用户“登录”

  • Authorization(授权): 访问控制。比如某个用户是否具有某个操作的使用权限。

  • Session Management(会话管理): 特定于用户的会话管理,甚至在非web 或 EJB 应用程序。

  • Cryptography(加密): 在对数据源使用加密算法加密的同时,保证易于使用。

三、应用程序

1.pom.xml文件导入依赖包

shiro依赖

        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.9.0</version>
        </dependency>

EhCache依赖

        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <version>1.2.3</version>
        </dependency>
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache-core</artifactId>
            <version>2.5.3</version>
        </dependency>

2.创建 mybatis-config.xml 配置文件(链接数据库)

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.cj.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost:3306/rbac?characterEncoding=utf8&amp;useSSL=false&amp;serverTimezone=UTC"/>
                <property name="username" value="root"/>
                <property name="password" value="root"/>
            </dataSource>
        </environment>
    </environments>
    <mappers>
        <mapper resource="mapper/SysUserMapper.xml"/>
    </mappers>
</configuration>

创建ehcache.xml文件(缓存)

<?xml version="1.0" encoding="UTF-8"?>
<ehcache >
    <defaultCache
            maxElementsInMemory="1000"
            maxElementsOnDisk="10000000"
            eternal="false"
            overflowToDisk="false"
            diskPersistent="false"
            timeToIdleSeconds="120"
            timeToLiveSeconds="120"
            diskExpiryThreadIntervalSeconds="120"
            memoryStoreEvictionPolicy="LRU">
    </defaultCache>
</ehcache>

3.建立各层

eg:

service层:

package com.wn.rbac.service.impl;

import com.wn.rbac.entity.SysUser;
import com.wn.rbac.mapper.SysUserMapper;
import com.wn.rbac.service.UserService;
import com.wn.rbac.util.DBTools;
import org.apache.ibatis.session.SqlSession;

import java.util.Set;

/**
 * @author :fengSir
 * @date :Created By 2022-06-12 15:18
 * @description :TODO
 */
public class UserServiceImpl implements UserService {
    @Override
    public SysUser getUserByTelephone(String telephone) {
        SqlSession sqlSession =  DBTools.getSession();
        SysUserMapper userMapper =  sqlSession.getMapper(SysUserMapper.class);
        SysUser user = userMapper.selectUserByPwd(telephone);
        sqlSession.commit();
        return user;
    }

    @Override
    public Set<String> getRolesByTelephone(String telephone) {
        SqlSession sqlSession =  DBTools.getSession();
        SysUserMapper userMapper =  sqlSession.getMapper(SysUserMapper.class);
        Set<String> set = userMapper.selectRolesByTelphone(telephone);
        sqlSession.commit();
        return set;
    }

    @Override
    public Set<String> getPersByTelephone(String telephone) {
        SqlSession sqlSession =  DBTools.getSession();
        SysUserMapper userMapper =  sqlSession.getMapper(SysUserMapper.class);
        Set<String> set = userMapper.selectPersByTelephone(telephone);
        sqlSession.commit();
        return set;
    }

    public static void main(String[] args) {
        System.out.println(new UserServiceImpl().getRolesByTelephone("13892845500"));
    }
}

工具类:

package com.wn.rbac.util;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class DBTools {
    private static SqlSessionFactory sqlSessionFactory;
    static{

        String resource = "mybatis-config.xml";
        InputStream inputStream=null;
        try {
            inputStream = Resources.getResourceAsStream(resource);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

    }
    public static SqlSession getSession(){
        return sqlSessionFactory.openSession();
    }
}

4.自定义Realm

package com.wnxy.myrealm.util;

import com.wnxy.myrealm.entity.SysUser;
import com.wnxy.myrealm.service.SysUserService;
import com.wnxy.myrealm.service.impl.SysUserServiceImpl;
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.apache.shiro.util.ByteSource;

import java.util.Set;

/**
 * @author Mrz
 * @date 2022/8/15 18:55
 */
public class MyRealm extends AuthorizingRealm {
    private SysUserService service = new SysUserServiceImpl();
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("负责验权");
        //获取tel
        String principal = (String) principalCollection.getPrimaryPrincipal();
        //访问后台数据库查询出对应的角色和权限
        Set<String> strings = service.selectRolesByTel(principal);
        Set<String> strings1 = service.selectPersByTel(principal);
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        simpleAuthorizationInfo.setRoles(strings);
        simpleAuthorizationInfo.setStringPermissions(strings1);
        return simpleAuthorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        System.out.println("负责认证");
        String tel = (String)authenticationToken.getPrincipal();
        SysUser sysUser = service.selectSysUserByTel(tel);
        SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(tel, sysUser.getPassword(), getName());
        //解盐(在已加入的算法“MD5”和迭代次数1024的基础上,加盐,最后得出用户输入的密码的加密结果,和数据库里的加密结果进行比对,最终返回true或false)
        simpleAuthenticationInfo.setCredentialsSalt(ByteSource.Util.bytes(tel));
        return simpleAuthenticationInfo;
    }
}

5.测试(Shiro执行流程(包括加密和缓存))

@Test
    void testShiro(){
        //缓存配置
        EhCacheManager ehCacheManager = new EhCacheManager();
        ehCacheManager.setCacheManagerConfigFile("classpath:ehcache.xml");
        //认证匹配器
        HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
        hashedCredentialsMatcher.setHashIterations(1024);
        hashedCredentialsMatcher.setHashAlgorithmName("MD5");
        //1、得到安全管理器
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        //绑定缓存
        defaultSecurityManager.setCacheManager(ehCacheManager);
        //2、得到领域
        MyRealm myRealm = new MyRealm();
        //绑定认证匹配器
        myRealm.setCredentialsMatcher(hashedCredentialsMatcher);
        //3、将领域绑定到securityManager
        defaultSecurityManager.setRealm(myRealm);
        //4、得到安全管理工具
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        //5、得到主体
        Subject subject = SecurityUtils.getSubject();
        //6、得到验证信息
        UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken("13892845500", "123456");
        //验证
        try {
            subject.login(usernamePasswordToken);
            log.info("是否拥有管理角色:{}",subject.hasRole("管理员"));
            log.info("是否拥有权限管理权限:{}",subject.isPermitted("权限管理"));
            log.info("登录成功");
        }catch (UnknownAccountException uae) {
            log.info("未知账号");
        }catch (IncorrectCredentialsException ice) {
            log.info("密码错误");
        }catch (LockedAccountException lae){
            log.info("账户被锁");
        }catch (AuthenticationException e) {
            log.info("未知异常");
        }

    }

(显示加密结果)

@Test
    void testMD5(){
        SimpleHash md5 = new SimpleHash("MD5", "123456", "13892845500",1024);
        log.info(md5.toHex());
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值