关于学习Shiro的一些笔记总结(一)

获取源码和笔记地址:https://gitee.com/monologue_zsj/shiro.git


- Subject:主体
  - 访问系统的用户,主体可以是用户、程序等,进行认证的都称为主体;
- Principal:身份信息
  - 是主体(subject)进行身份认证的标识,标识必须具有唯一性,如用户名、手机号、邮箱地址等,一个主体可以有多个身份,但是必须有一个主身份(Primary Principal)。
- credential:凭证信息
  - 是只有主体自己知道的安全信息,如密码、证书等。

关于学习Shiro的一些笔记总结(一)

1、shiro-single

 <!--Shrio依赖(maven 项目)-->
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-core</artifactId>
    <version>1.5.3</version>
</dependency>
#shiro.ini	模拟数据
[users]
xiaozhang=123
zhangsan=123456
lisi=789

1.1 测试认证

/**
 * Created by Monologue_zsj on 2021/3/7 9:58
 * Author:小脸儿红扑扑
 * Description:测试认证
 */
public class TestAuthenticator {
    public static void main(String[] args) {

        //1、创建安全管理器
        DefaultSecurityManager securityManager = new DefaultSecurityManager();
        //2、给安全管理器设置Realm
        securityManager.setRealm(new IniRealm("classpath:shiro.ini"));
        //3、SecurityUtils   给全局安全工具类设置安全管理器
        SecurityUtils.setSecurityManager(securityManager);
        //4、关键对象 subject 主体
        Subject subject = SecurityUtils.getSubject();
        //5、创建令牌
        UsernamePasswordToken token = new UsernamePasswordToken("xiaozhang", "123");
        try {
            System.out.println("认证状态========>" + subject.isAuthenticated());
            subject.login(token);    //用户认证
            System.out.println("认证状态========>" + subject.isAuthenticated());
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            System.out.println("认证失败========> 用户名不存在...");
        }catch (IncorrectCredentialsException e) {
            e.printStackTrace();
            System.out.println("认证失败========> 密码错误...");
        }
    }
}

1.2 自定义Realm

 

/**
 * Created by Monologue_zsj on 2021/3/7 10:43
 * Author:小脸儿红扑扑
 * Description:自定义Realm实现,将认证/授权的数据的来源转为数据库的实现
 */
public class CustomerRealm extends AuthorizingRealm {

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        //在token中获取用户名
        String principal = (String) token.getPrincipal();
        //根据身份信息使用jdbc/mybatis...查询相关数据库
        if ("xiaozhang".equals(principal)) {
            /**
             * 参数1:返回数据库中正确的用户名
             * 参数2:返回数据库中正确的密码
             * 参数3:提供当前Realm的名字 this.getName()
             */
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(principal, "123", getName());

            return simpleAuthenticationInfo;
        }
        return null;
    }
}
/**
 * Created by Monologue_zsj on 2021/3/7 10:46
 * Author:小脸儿红扑扑
 * Description:使用自定义Realm
 */
public class TestCustomerRealmAuthenticator {
    public static void main(String[] args) {

        //创建SecurityManager
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        //设置自定义Realm
        defaultSecurityManager.setRealm(new CustomerRealm());
        //给全局安全工具类设置安全管理器
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        //通过安全工具类获取subject
        Subject subject = SecurityUtils.getSubject();
        //创建token
        UsernamePasswordToken token = new UsernamePasswordToken("xiaozhang", "123");
        try {
            subject.login(token);
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            System.out.println("认证失败========> 用户名不存在...");
        }catch (IncorrectCredentialsException e) {
            e.printStackTrace();
            System.out.println("认证失败========> 密码错误...");
        }

    }
}

1.3 MD5加密

/**
 * Created by Monologue_zsj on 2021/3/7 12:15
 * Author:小脸儿红扑扑
 * Description:MD5加密
 */
public class TestShiroMD5 {
    public static void main(String[] args) {

        //创建一个md5算法
//        Md5Hash md5Hash = new Md5Hash();
//        md5Hash.setBytes("123456".getBytes());
//        String hex = md5Hash.toHex();
//        System.out.println(hex);

        //使用MD5
        Md5Hash md5Hash = new Md5Hash("123456");
        System.out.println(md5Hash.toHex());

        //使用MD5 + salt 处理
        Md5Hash md5Salt = new Md5Hash("123456", "X0*7ps");
        System.out.println(md5Salt);

        //使用MD5 + salt + hash散列(散列次数)
        Md5Hash hash = new Md5Hash("123456", "X0*7ps", 1024);
        System.out.println(hash);
    }
}

/*
	e10adc3949ba59abbe56e057f20f883e	MD5
    e99a0dee78d3c1f71609cead42047675    MD5 + salt
    955224a95d4161ad8bd84f7ede979c02    MD5 + salt + hash
*/

Shiro认证对密码进行加密案例:

/**
 * Created by Monologue_zsj on 2021/3/7 12:23
 * Author:小脸儿红扑扑
 * Description:使用自定义Realm加入 md5 + salt + hash
 */
public class CustomerMD5Realm extends AuthorizingRealm {

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {

        //获取身份信息
        String principal = (String) token.getPrincipal();
        //根据用户名查询数据库
        if ("xiaozhang".equals(principal)) {
            /**
             * 参数1:数据库用户名
             * 参数2:数据库md5 + salt之后的密码
             * 参数3:注册时的随机盐
             * 参数4:realm的名字
             */
            return new SimpleAuthenticationInfo(principal,
                    "955224a95d4161ad8bd84f7ede979c02",
                    ByteSource.Util.bytes("X0*7ps"),
                    this.getName());
        }
        return null;
    }
}
/**
 * Created by Monologue_zsj on 2021/3/7 10:46
 * Author:小脸儿红扑扑
 * Description:使用自定义Realm
 */
public class TestCustomerMD5RealmAuthenticator {
    public static void main(String[] args) {

        //创建SecurityManager
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        //注入Realm
        CustomerMD5Realm realm = new CustomerMD5Realm();
        //设置Realm使用hash凭证匹配器
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        //使用的算法
        credentialsMatcher.setHashAlgorithmName("md5");
        //散列的次数
        credentialsMatcher.setHashIterations(1024);
        realm.setCredentialsMatcher(credentialsMatcher);
        //设置自定义Realm
        defaultSecurityManager.setRealm(realm);
        //给全局安全工具类设置安全管理器
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        //通过安全工具类获取subject
        Subject subject = SecurityUtils.getSubject();
        //创建token,认证
        UsernamePasswordToken token = new UsernamePasswordToken("xiaozhang", "123456");
        try {
            subject.login(token);
            System.out.println("登录成功...");
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            System.out.println("认证失败========> 用户名不存在...");
        }catch (IncorrectCredentialsException e) {
            e.printStackTrace();
            System.out.println("认证失败========> 密码错误...");
        }

    }
}

1.4 授权

关于学习Shiro的一些笔记总结(一)

授权方式

- 基于角色的访问控制

  • RBAC(Role-Based Access Control)是以角色为中心进行访问控制

if(subject.hasRole("admin")) {
    //操作什么资源
}

- 基于资源的访问控制

  • RBAC(Resource-Based Access Control)是以资源为中心进行访问控制

if(subject.isPermission("user:update:01")){	//资源实例
    //对01用户进行修改
}
if(subject.isPermission("user:update:*")){	//资源类型
    //对01用户进行修改
}

权限字符串(资源标识符:操作:资源实例标识符)

  • 用户创建权限:user:create,或user:create:*

  • 用户修改实例001权限:user:update:001

  • 用户实例001的所有权限:user:*:001

/**
 * Created by Monologue_zsj on 2021/3/7 12:23
 * Author:小脸儿红扑扑
 * Description:使用自定义Realm加入 md5 + salt + hash
 */
public class CustomerMD5Realm extends AuthorizingRealm {

    //授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {

        String primaryPrincipal = (String) principal.getPrimaryPrincipal();
        System.out.println("身份信息(用户名)===============》" + primaryPrincipal);
        //根据身份信息获取当前用户的角色信息,以及权限信息
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        //将数据库中查询角色信息赋给权限对象
        simpleAuthorizationInfo.addRole("admin");
        simpleAuthorizationInfo.addRole("user");

        //将数据库中查询权限信息赋值个给权限对象
        simpleAuthorizationInfo.addStringPermission("user:*:01");
        simpleAuthorizationInfo.addStringPermission("product:*:*");

        return simpleAuthorizationInfo;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        ...
    }
}
/**
 * Created by Monologue_zsj on 2021/3/7 10:46
 * Author:小脸儿红扑扑
 * Description:使用自定义Realm
 */
public class TestCustomerMD5RealmAuthenticator {
    public static void main(String[] args) {

		...
        //认证的用户进行授权
        if (subject.isAuthenticated()) {    //认证成功
            //基于角色的权限控制
            System.out.println("hasRole:" + subject.hasRole("admin"));
            System.out.println("__________________________________________________________________");
            //基于多角色的权限控制
            System.out.println("hasAllRoles:" + subject.hasAllRoles(Arrays.asList("admin", "user")));
            System.out.println("__________________________________________________________________");
            //是否具有其中一个角色
            for (boolean role : subject.hasRoles(Arrays.asList("admin", "user", "super"))) {
                System.out.println("hasRoles:" + role);
            }
            System.out.println("__________________________________________________________________");
            //基于权限字符串的访问控制      资源标识符:操作:资源类型
            System.out.println("isPermitted:" + subject.isPermitted("user:*:01"));
            System.out.println("__________________________________________________________________");
            //分别具有那些权限
            for (boolean permitted : subject.isPermitted("user:*:01", "order:*:10")) {
                System.out.println(permitted);
            }
            System.out.println("__________________________________________________________________");
            //同时具有那些权限 
            System.out.println(subject.isPermittedAll("user:*:01", "product:*"));
        }
    }
}

 

 

 

 

上一篇:Asp.Net2.0下C#环境 Login控件实现用户登录


下一篇:Mac 下使用svn