shiro分步学习,详细-------基础篇

什么是权限管理 

 

一、使用ini完成认证,入门

1、创建shiro.ini文件,模拟数据库查询

#固定写法-创建用户对象
[users]
# 账号=密码
zhangchao=666

2、测试类

package com.zhangchao.shiro.study;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.junit.Test;

/**
 * 〈〉
 *
 * @author zc
 * @create 2018/11/20
 */
public class ShiroTest {

    @Test
    public void testLogin(){

        //1、创建SecurityManager工厂,加载配置文件,创建工厂对象
        Factory<SecurityManager> managerFactory = new IniSecurityManagerFactory("classpath:shiro.ini");
        //2、通过工厂对象,创建SecurityManager对象
        SecurityManager securityManager = managerFactory.getInstance();

        //3、将securityManager绑定到当前运行环境,让系统随时可以访问securityManager对象
        SecurityUtils.setSecurityManager(securityManager);
        //4、创建当前登陆主体
        Subject subject = SecurityUtils.getSubject();
        //5、收集主体登陆的身份凭证,即账号,密码
        UsernamePasswordToken token = new UsernamePasswordToken("zhangchao", "666");
        //6、主体登陆
        try {
            subject.login(token);
        }catch (Exception e){
            e.printStackTrace();
        }
        //验证是否登陆 true为登陆
        System.out.println("验证是否登陆  : "+ subject.isAuthenticated());
        //7、登出
        subject.logout();
        //验证是否登出  false为登出
        System.out.println("验证是否登出  : "+ subject.isAuthenticated());
    }


}

 

二 、自定义realm

1、自定义reaml,继承AuthorizingRealm 重写三个方法,getName、doGetAuthorizationIngo、doGetAuthenticationInfo

package com.zhangchao.shiro.study;

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.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

/**
 * 〈自定义realm〉
 *
 * @author 22902
 * @create 2018/11/20
 */
public class MyRealm extends AuthorizingRealm {

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

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

    /**
     * 认证操作
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
      //token 表示登陆时包装的username和password
        //通过用户名到数据库中查询用户信息,封装成一个authenticationInfo 对象返回,方便认证器进行对比
        //获取token中用户名
       String username = (String) token.getPrincipal();
        System.out.println(username);
        //通过用户名查询数据库,将改用户对应数据返回账号密码
        if (!"zhangchao".equals(username)){
            return null;
        }
        String password = "666";
        //info对象表示realm登陆对比信息,参数1:用户信息(真实登陆中是登陆对象user对象),参数2:密码,参数3:当前realm名
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password, getName());

        return info;
    }
}

2、配置ini文件,指定使用自定义realm

#声明一个realm
myRealm=com.zhangchao.shiro.study.MyRealm
#这里就是我们注入realm的地方
securityManager.realms=$myRealm

3、加载配置文件shiro-realm.ini ,执行登陆操作

 @Test
    public void testLogin(){

        //1、创建SecurityManager工厂,加载配置文件,创建工厂对象
        Factory<SecurityManager> managerFactory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");
        //2、通过工厂对象,创建SecurityManager对象
        SecurityManager securityManager = managerFactory.getInstance();

        //3、将securityManager绑定到当前运行环境,让系统随时可以访问securityManager对象
        SecurityUtils.setSecurityManager(securityManager);
        //4、创建当前登陆主体
        Subject subject = SecurityUtils.getSubject();
        //5、收集主体登陆的身份凭证,即账号,密码
        UsernamePasswordToken token = new UsernamePasswordToken("zhangchao", "666");
        //6、主体登陆
        try {
            subject.login(token);
        }catch (UnknownAccountException e){
            e.printStackTrace();
            System.out.println("用户名错误");
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            System.out.println("密码错误");
        }
        catch (Exception e){
            e.printStackTrace();
        }
        //验证是否登陆
        System.out.println("验证是否登陆  : "+ subject.isAuthenticated());
        //7、登出
        subject.logout();
        //验证是否登出
        System.out.println("验证是否登出  : "+ subject.isAuthenticated());
    }

三、加密realm登入登出

测试下md5

package com.zhangchao.shiro.study;

import org.apache.shiro.crypto.hash.Md5Hash;
import org.junit.Test;

/**
 * 〈MD5加密〉
 *
 * @author 22902
 * @create 2018/11/21
 */
public class MD5Test {

    @Test
    public void md5Test() {
        //密码  明文
        String password = "666";
        //加密md5  fae0b27c451c728867a567e8c1bb4e53
        Md5Hash md5Hash = new Md5Hash(password);
        System.out.println(md5Hash);
        //加密md5 + 盐  8ab1db3f57dfd36248b1dcd7adc12ab0
        md5Hash = new Md5Hash(password,"zhangchao");
        System.out.println(md5Hash);
        //加密md5 + 盐 + 散列次数  e925117800d6e0b60098b681809b3789
        md5Hash = new Md5Hash(password,"zhangchao",5);
        System.out.println(md5Hash);


    }
}

 

1、自定义加密之后realm

package com.zhangchao.shiro.study;

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.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

/**
 * 〈〉
 *
 * @author 22902
 * @create 2018/11/21
 */
public class PasswordRealm extends AuthorizingRealm {

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

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

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //token 表示登陆时包装的username和password
        //通过用户名到数据库中查询用户信息,封装成一个authenticationInfo 对象返回,方便认证器进行对比
        //获取token中用户名
        String username = (String) token.getPrincipal();
        System.out.println(username);
        //通过用户名查询数据库,将改用户对应数据返回账号密码
        if (!"zhangchao".equals(username)){
            return null;
        }
        //模拟数据库中保存加密之后密文: 666 + 账号(盐) + 三列次数
        String password = "e925117800d6e0b60098b681809b3789";
        //info对象表示realm登陆对比信息,参数1:用户信息(真实登陆中是登陆对象user对象),参数2:密码,参数3:盐,参数4:当前realm名
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password, ByteSource.Util.bytes("zhangchao"), getName());

        return info;
    }
}

2、配置ini配置文件

[main]
#定义凭证匹配器
credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher
#散列算法
credentialsMatcher.hashAlgorithmName=md5
#散列次数 md5| sha
credentialsMatcher.hashIterations=5
#将凭证匹配器设置到realm
myRealm=com.zhangchao.shiro.study.PasswordRealm
myRealm.credentialsMatcher=$credentialsMatcher
securityManager.realms=$myRealm

3、测试

package com.zhangchao.shiro.study;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.junit.Test;

/**
 * 〈〉
 *
 * @author 22902
 * @create 2018/11/20
 */
public class ShiroTest {

    @Test
    public void testLogin(){

        //1、创建SecurityManager工厂,加载配置文件,创建工厂对象
        Factory<SecurityManager> managerFactory = new IniSecurityManagerFactory("classpath:shiro-cryptography.ini");
        //2、通过工厂对象,创建SecurityManager对象
        SecurityManager securityManager = managerFactory.getInstance();

        //3、将securityManager绑定到当前运行环境,让系统随时可以访问securityManager对象
        SecurityUtils.setSecurityManager(securityManager);
        //4、创建当前登陆主体
        Subject subject = SecurityUtils.getSubject();
        //5、收集主体登陆的身份凭证,即账号,密码
        UsernamePasswordToken token = new UsernamePasswordToken("zhangchao", "666");
        //6、主体登陆
        try {
            subject.login(token);
        }catch (UnknownAccountException e){
            e.printStackTrace();
            System.out.println("用户名错误");
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            System.out.println("密码错误");
        }
        catch (Exception e){
            e.printStackTrace();
        }
        //验证是否登陆
        System.out.println("验证是否登陆  : "+ subject.isAuthenticated());
        //7、登出
        subject.logout();
        //验证是否登出
        System.out.println("验证是否登出  : "+ subject.isAuthenticated());
    }


}

四、rbac权限模型理解

 

五、ini方式检查用户拥有权限

 授权方式(三种)

权限表达式定义 

1、配置ini文件

[users]
# 用户zhagnchao的密码为666,拥有role1和role2两个角色
zhangchao=666,role1,role2
lisi=888,role2

[roles]
#角色role1对资源user拥有create、update权限
role1=user:create,user:update
#角色role2对资源user拥有create、delete权限
role2=user:create,user:delete
#角色role3对资源拥有create权限
role3=user:create

2、加载配置文件,检查是否拥有角色

package com.zhangchao.shiro.study;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.junit.Test;

import java.util.Arrays;

/**
 * 〈〉
 *
 * @author 22902
 * @create 2018/11/20
 */
public class ShiroTest {

    @Test
    public void testLogin(){

        //1、创建SecurityManager工厂,加载配置文件,创建工厂对象
        Factory<SecurityManager> managerFactory = new IniSecurityManagerFactory("classpath:shiro-permission.ini");
        //2、通过工厂对象,创建SecurityManager对象
        SecurityManager securityManager = managerFactory.getInstance();

        //3、将securityManager绑定到当前运行环境,让系统随时可以访问securityManager对象
        SecurityUtils.setSecurityManager(securityManager);
        //4、创建当前登陆主体
        Subject subject = SecurityUtils.getSubject();
        //5、收集主体登陆的身份凭证,即账号,密码
        UsernamePasswordToken token = new UsernamePasswordToken("zhangchao", "666");
        //6、主体登陆
        try {
            subject.login(token);
            //进行授权操作时前提:用户必须通过认证
            //判断用户是否拥有某个角色
            boolean a = subject.hasRole("role1");
            System.out.println("用户是否有role1角色 :" + a);
            //判断当前用户是否拥有一些角色,true表示全部拥有,false表示bu全部拥有
            boolean b = subject.hasAllRoles(Arrays.asList("role1", "role2"));
            System.out.println("用户是否有role1、role2角色 :" + b);
            //判断当前用户是否拥有一些角色,返回boolean数组,true表示拥有,false表示没有
            boolean[] c = subject.hasRoles(Arrays.asList("role1", "role2","role3"));
            System.out.println("用户是否有role1、role2角色 :" + Arrays.toString(c));
            //判断当前用户是否拥有某个角色,如果拥有该角色,不做任何操作,如果没有,报错UnauthorizedException
//            subject.checkRoles("role1","role2","role3");
            subject.checkRole("role2");
        }catch (UnknownAccountException e){
            e.printStackTrace();
            System.out.println("用户名错误");
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            System.out.println("密码错误");
        }
        catch (Exception e){
            e.printStackTrace();
        }
        //验证是否登陆
        System.out.println("验证是否登陆  : "+ subject.isAuthenticated());
        //7、登出
        subject.logout();
        //验证是否登出
        System.out.println("验证是否登出  : "+ subject.isAuthenticated());
    }


}

六、ini方式检查用户拥有权限

1、ini配置文件,跟五中是一样的

2、加载配置文件,检查是否拥有权限

package com.zhangchao.shiro.study;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.junit.Test;

import java.util.Arrays;

/**
 * 〈〉
 *
 * @author 22902
 * @create 2018/11/20
 */
public class ShiroTest {

    @Test
    public void testLogin(){

        //1、创建SecurityManager工厂,加载配置文件,创建工厂对象
        Factory<SecurityManager> managerFactory = new IniSecurityManagerFactory("classpath:shiro-permission.ini");
        //2、通过工厂对象,创建SecurityManager对象
        SecurityManager securityManager = managerFactory.getInstance();

        //3、将securityManager绑定到当前运行环境,让系统随时可以访问securityManager对象
        SecurityUtils.setSecurityManager(securityManager);
        //4、创建当前登陆主体
        Subject subject = SecurityUtils.getSubject();
        //5、收集主体登陆的身份凭证,即账号,密码
        UsernamePasswordToken token = new UsernamePasswordToken("zhangchao", "666");
        //6、主体登陆
        try {
            subject.login(token);
            //进行授权操作时前提:用户必须通过认证
            //判断当前用户是否拥有某个权限,true表示拥有,false表示没有
            boolean a = subject.isPermitted("user:create");
            System.out.println("当前用户是否拥有权限: "+a);
            //判断当前用户是否拥有某个权限,true表示都拥有,false表示不全部拥有
            boolean b = subject.isPermittedAll("user:create", "user:update","user:delete");
            System.out.println("当前用户是否拥有权限: "+b);
            //判断当前用户是否拥有某个权限,返回boolean数组,true表示都拥有,false表示不拥有
            boolean[] booleans = subject.isPermitted("user:create", "user:update");
            System.out.println(Arrays.toString(booleans));
            //判断当前用户是否拥有某个权限,如果没有报错UnauthorizedException,有不操作
            subject.checkPermission("user:create");

        }catch (UnknownAccountException e){
            e.printStackTrace();
            System.out.println("用户名错误");
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            System.out.println("密码错误");
        }
        catch (Exception e){
            e.printStackTrace();
        }
        //验证是否登陆
        System.out.println("验证是否登陆  : "+ subject.isAuthenticated());
        //7、登出
        subject.logout();
        //验证是否登出
        System.out.println("验证是否登出  : "+ subject.isAuthenticated());
    }


}

七、自定义realm授权

1、自定义PermissionRealm类,继承AuthorizingRealm,重写三个方法,getName、doGetAuthorizationIngo、doGetAuthenticationInfo

package com.zhangchao.shiro.study;

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 java.util.ArrayList;
import java.util.List;

/**
 * 〈自定义realm〉
 *
 * @author 22902
 * @create 2018/11/20
 */
public class PermissionRealm extends AuthorizingRealm {

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

    /**
     * 授权操作
     * @param principal  用户凭证信息
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
        //当前用户信息,用户凭证
        String username = (String) principal.getPrimaryPrincipal();
        //模拟查询数据库,查询用户实现指定角色,权限
        List<String> roles = new ArrayList<>();
        List<String> permissions = new ArrayList<>();
        //假设用户再数据库中有role1角色
        roles.add("role1");
        //假设用户在数据库中有user:create权限
        permissions.add("user:create");
        //返回用户在数据库中的权限及角色
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addStringPermissions(permissions);
        info.addRoles(roles);
        return info;

    }

    /**
     * 认证操作
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
      //token 表示登陆时包装的username和password
        //通过用户名到数据库中查询用户信息,封装成一个authenticationInfo 对象返回,方便认证器进行对比
        //获取token中用户名
       String username = (String) token.getPrincipal();
        System.out.println(username);
        //通过用户名查询数据库,将改用户对应数据返回账号密码
        if (!"zhangchao".equals(username)){
            return null;
        }
        String password = "666";
        //info对象表示realm登陆对比信息,参数1:用户信息(真实登陆中是登陆对象user对象),参数2:密码,参数3:当前realm名
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username, password, getName());

        return info;
    }
}

2、配置ini文件 shiro-permission-realm.ini

#声明一个realm
myRealm=com.zhangchao.shiro.study.PermissionRealm
#这里就是我们注入realm的地方
securityManager.realms=$myRealm

3、加载配置文件,测试

package com.zhangchao.shiro.study;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.junit.Test;

/**
 * 〈〉
 *
 * @author 22902
 * @create 2018/11/20
 */
public class ShiroTest {

    @Test
    public void testLogin(){

        //1、创建SecurityManager工厂,加载配置文件,创建工厂对象
        Factory<SecurityManager> managerFactory = new IniSecurityManagerFactory("classpath:shiro-permission-realm.ini");
        //2、通过工厂对象,创建SecurityManager对象
        SecurityManager securityManager = managerFactory.getInstance();

        //3、将securityManager绑定到当前运行环境,让系统随时可以访问securityManager对象
        SecurityUtils.setSecurityManager(securityManager);
        //4、创建当前登陆主体
        Subject subject = SecurityUtils.getSubject();
        //5、收集主体登陆的身份凭证,即账号,密码
        UsernamePasswordToken token = new UsernamePasswordToken("zhangchao", "666");
        //6、主体登陆
        try {
            subject.login(token);
            boolean a = subject.isPermitted("user:create");
            System.out.println("是否拥有权限: "+a);
            boolean b = subject.hasRole("role1");
            System.out.println("是否拥有角色: "+b);

        }catch (UnknownAccountException e){
            e.printStackTrace();
            System.out.println("用户名错误");
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            System.out.println("密码错误");
        }
        catch (Exception e){
            e.printStackTrace();
        }
        //验证是否登陆
        System.out.println("验证是否登陆  : "+ subject.isAuthenticated());
        //7、登出
        subject.logout();
        //验证是否登出
        System.out.println("验证是否登出  : "+ subject.isAuthenticated());
    }


}

 授权过程如下图

 

到现在基础篇写完了,这也是我自己学习视频并实践的结果,每天进步一点点,每天学习一点点,努力给我爱的人更好的未来!

 

感谢姚老师 ,视频地址点击进入

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值