美文网首页shiro
shrio权限框架

shrio权限框架

作者: 磨陀货_ | 来源:发表于2019-09-26 15:44 被阅读0次
    shiro Spring security
    粗粒度 细粒度
    功能够用 功能更细更多
    学习难度低 学习难度高

    Shiro四大基石

    名称 意思
    Authentication 身份验证:登录--- 噢搜体k森
    Authorization 授权:权限判断 ---- 噢搜锐z森
    Cryptography 密码学:加密
    Session Management 会话管理:session
    会话管理:

    用户登录,会把用户名和密码传到后台,后台会去数据库中找有没有这个人,如果有登录成功,会存在session中(通过HttpSession。web项目中才有,CS中就没有这个类了)。但是这里session提供了这个功能,不用在考虑有没有HttpSession


    核心类

    • Subject(啥不j可特)---当前用户(游客/登录用户)如果要登录需要令牌
    • SecurityManager (C可瑞 麦泥着)---- Shiro的权限管理器【Shiro所有功能都是通过他】(最重要)
    • Reaim(入母) ---- 去拿到登录等的值【拿数据、获取数据】

    Shiro官方有所有案例


    我们现在用的是SpringMVC所以使用路径判断xue微好一点
    其实两个方式都差不多,都可以用,Controller.save()是Struts2好一点

    权限表关系(重)

    • 用户----角色 --- 多对多 【一个人有多个角色,一个角色有多个人】
    • 角色-----权限----多对多 【一个角色有多个功能,一个功能对应多个角色】

    速成案例

    1.新建maven项目

    2.导jar包

    <!--shiro支持包-->
    <dependencies>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.4.0</version>
        </dependency>
    <!--日志支持包-->
        <dependency>
            <groupId>commons-logging</groupId>
            <artifactId>commons-logging</artifactId>
            <version>1.2</version>
        </dependency>
    <!--测试包-->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
    

    3.导入shiro.ini 文件

    一、获取SecurityManager对象

    1.获取Shiro.ini文件
    2.从工厂中获取到SecurityManager对象


    二、把SecurityManager对象设置到上下文中

    三、获取到当前用户(如果没有登录就是游客)

    1.判断短是否登录----isAuthenicated()


    2.如果没有登录就让他登录
    ①登录需要令牌----UsernamePasswordToken
    ②根据令牌实现登录
    3,注销登录 ---- login()
    4.try一下 如果输错报出错误
    ①Unknown(未知的)Account(账号)Exception---账户错误
    ②Incorrect(错误的)Credentials(凭证)Exception--密码错误
    ③AuthenicationException----最大的错误(神秘错误)

    image.png
    hasRole() ------ 判断是否是存在角色(返回true、false)角色判断
    image.png
    isPermitted() ------ 判断是否有该权限(返回true/false)权限判断
    image.png

    定义一个自己的Realm 继承extends AuthorizingRealm
    继承完就要实现两个方法 一个授权一个登陆

    完成版

    public class ShiroTest {
        @Test
        public void ShiroTest() throws Exception{
            //拿到SecurityManager核心对象
            IniSecurityManagerFactory factory = new IniSecurityManagerFactory("classpath:shiro.ini");
            SecurityManager securityManager = factory.getInstance();
    
            //把SecurityManager对象放到当前的上下文中
            SecurityUtils.setSecurityManager(securityManager);
    
            //拿到当前用户
            Subject subject = SecurityUtils.getSubject();
    
            //获得令牌 ----  判断
            //④.如果没有登录,让他登录(需要令牌)
            if(!subject.isAuthenticated()){
                try {
                    //用户名密码令牌
                    AuthenticationToken token = new UsernamePasswordToken("root","123456");
                    //登录功能
                    subject.login(token);
                } catch (UnknownAccountException e) {//Unknown(未知)Account(账号)Exception
                    e.printStackTrace();
                    System.out.println("用户名错误!");
                } catch (IncorrectCredentialsException e) {//Incorrect(不正确的)Credentials(凭证;证书)Exception
                    e.printStackTrace();
                    System.out.println("密码错误!");
                }catch (AuthenticationException e){
                    e.printStackTrace();
                    System.out.println("出现一个神迷的错误!!!!");
                }
            }
    
            //对于角色的判断
            System.out.println("是否是admin角色:"+subject.hasRole("admin"));
            System.out.println("是否是it角色:"+subject.hasRole("it"));
    
            //判断相应的权限
            System.out.println("是否是employee:save权限:"+subject.isPermitted("employee:save"));
            System.out.println("是否是employee:update权限:"+subject.isPermitted("employee:update"));
            System.out.println("是否是department:save权限:"+subject.isPermitted("department:save"));
    
            //判断这个用户是否登录
            System.out.println("是否登录:" + subject.isAuthenticated());
            //注销,退出,登出
            subject.logout();
            System.out.println("是否登录:" + subject.isAuthenticated());
        }
    }
    

    上面都是在用Shiro.ini文件代替数据库玩的。现在开始用数据库来操作

    案例2:自定义Realm

    身份认证的代码

    /**
     * 自定义一个Realm
     */
    public class MyRealm extends AuthorizingRealm {
    
        //获取到这个Realm的名称(随便取)
        @Override
        public String getName() {
            return "MyRealm";
        }
    
        //进行授权的认证
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
            return null;
        }
    
        //进行登录的认证
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
            //明显的知道:这个authenticationToken就是UsernamePasswordtoken
            //1.拿到闸门的令牌(用户名密码Token)--把令牌强转成用户名密码令牌
            UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
            String username = token.getUsername(); //2.拿到用户名(注:这个用户名是传过来的)
            //3.这里根据用户名到数据库中去获取密码(如果没有获取到,相当于这个用户不存在,就返回null值)
            String password = getByName(username);
            if(password==null){//判断如果password为空,那就返回空
                //3.返回空就是代表用户名不存在,shiro会自动帮你报UnknowAcctountException
                return null;
            }
            //创建一个简单的身份信息(把用户名与密码放进去-注:它会自动的比较获取的密码与你传过来的密码)
            //4.传的是数据库密码:他要把这个密码和令牌中的密码做比较,如果对应不上,就会报IncorrectCredentialsException
            SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(username,password,getName());
          //参数(主体(一般是当前用户名),密码,realm名字)--- 除了密码,其他都随意写
            return authenticationInfo;
        }
    
    //模拟从数据库中获取信息
        private String getByName(String username) {
            if("admin".equals(username)){
                return "123456";
            }else if("guest".equals(username)){
                return "abcd";
            }
            return null;
        }
    }
    

    创建测试登陆代 码

    @Test
    public void testMyRealm() throws Exception{
    
        //创建自己定义的Realm
        MyRealm myRealm = new MyRealm();
       //拿到SecurityManager对象
        DefaultSecurityManager securityManager = new DefaultSecurityManager();
        //把Realm放到securityManager中去 
       securityManager.setRealm(myRealm);
        //把SecurityManager放到上下文章
        //把权限管理器放到相应的环境中(我们可以在项目任何位置拿到)
        SecurityUtils.setSecurityManager(securityManager);
    
        //拿到当前用户(Subject就是当前用户,游客)
        Subject currentUser = SecurityUtils.getSubject();
    
        //判断一下是否登录
      System.out.println(""+ currentUser.isAuthenticated());
        //准备登录的令牌(准备用户名与密码)
        UsernamePasswordToken token = new UsernamePasswordToken("admin","123456");
    
        try {
            //根据令牌进行功能登录(当前用户进行登录)
            currentUser.login(token);
        } catch (UnknownAccountException e) {
            System.out.println("这个账号不存在!" + token.getPrincipal());
            e.printStackTrace();
        } catch (IncorrectCredentialsException ice) {
            System.out.println("这个密码不存在!" + token.getPrincipal());
            ice.printStackTrace();
        }catch (AuthenticationException e){//神秘错误
            System.out.println("i don't k");
        }
    }
    

    授权(权限功能)

    就是上面自定义Realm的时候,授权没有写,先搞得身份认证。现在回去在搞授权

    
    

    密码加密(Shiro---密码学)

    简单地说就是把看的懂得密码改成看不懂的

    知识点

    1.CS/BS :
    CS是qq,画图板等等,通过软件 --------- BS就是webqq,通过页面展示出来的

    2.粗粒度/细粒度:
    粗粒度比如能不能添加用户,能不能删除用户。 --------细粒度就是在粗粒度能完成的的功能下还能在精细一点。功能更完美一点


              java育儿园里的小学生“磨陀货”友情提供!!!
              请大家尊重原创,如要转载,请注明出处:
              转载自:https://www.jianshu.com/p/606e67f7cd1a,谢谢!!

              有任何疑问,欢迎加入Java交流群458443587(加群时请备注)

    相关文章

      网友评论

        本文标题:shrio权限框架

        本文链接:https://www.haomeiwen.com/subject/boebcctx.html