Shiro【Spirng、Shiroフィルタの承認、統合】


前言
本文の主な説明の知識点は以下の通りである.
  • Shiroライセンスの方法
  • について簡単に説明します.
  • とSpringの統合
  • 初期Shiroフィルタ
  • 一、Shiro授権
    前回はShiroの認証に関する知識を説明しましたが、今はShiroのライセンスを取りに来ました.
    Shiroが承認したプロセスと認証のプロセスは、実際にはそれほど悪くありません.
    1.1 Shiroがサポートするライセンス方式
    Shiroがサポートするライセンス方式は3つあります.
    
    Shiro          :
       :   if/else        :
    Subject subject = SecurityUtils.getSubject();
    if(subject.hasRole(“admin”)) {
    //   
    } else {
    //   
    }
       :      Java            :
    @RequiresRoles("admin")
    public void hello() {
    //   
    }
    JSP/GSP   : JSP/GSP            :
    
    
    

    1.2プログラミングライセンスの使用
    同様に、セキュリティマネージャを使用してライセンスを取得します.そのため、対応するプロファイルを構成する必要があります.
    shiro-permission.iniプロファイル:
    
    #  
    [users]
    #  zhang    123,     role1 role2    
    zhang=123,role1,role2
    wang=123,role2
    
    #  
    [roles]
    #  role1   user  create、update  
    role1=user:create,user:update
    #  role2   user  create、delete  
    role2=user:create,user:delete
    #  role3   user  create  
    role3=user:create
    
    
    
    #        :  :  :  (      :  )
    user:create:01          01    create  。
    user:create:         create  ,   user:create:*,           create  。
    user:*:01           01      。
    
    

    コードテスト:
    
    
        //     、      
        @Test
        public void testAuthorization() {
    
            //   SecurityManager  
            Factory factory = new IniSecurityManagerFactory(
                    "classpath:shiro-permission.ini");
    
            //   SecurityManager
            SecurityManager securityManager = factory.getInstance();
    
            //  SecurityManager         , spring  SecurityManager  spring   ,      
            SecurityUtils.setSecurityManager(securityManager);
    
            //   subject
            Subject subject = SecurityUtils.getSubject();
    
            //   token  
            UsernamePasswordToken token = new UsernamePasswordToken("zhangsan",
                    "123");
    
            //     
            try {
                subject.login(token);
            } catch (AuthenticationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
            System.out.println("    :" + subject.isAuthenticated());
            //          
    
            //        
            // hasRole      
            boolean ishasRole = subject.hasRole("role1");
            System.out.println("      " + ishasRole);
            // hasAllRoles        
            boolean hasAllRoles = subject.hasAllRoles(Arrays.asList("role1",
                    "role2", "role3"));
            System.out.println("      " + hasAllRoles);
    
            //   check      ,            
            // subject.checkRole("role13");
    
            //        
            // isPermitted       
            boolean isPermitted = subject.isPermitted("user:create:1");
            System.out.println("      " + isPermitted);
    
            boolean isPermittedAll = subject.isPermittedAll("user:create:1",
                    "user:delete");
            System.out.println("      " + isPermittedAll);
            //   check      ,            
            subject.checkPermission("items:create:1");
    
        }
    

    1.3承認のためにrealmをカスタマイズする
    一般的に、私たちの権限はデータベースからクエリーされ、私たちのプロファイルに基づいてペアリングされるわけではありません.そのため、reamlをカスタマイズし、reamlを比較するにはデータベースからクエリーされた権限が必要です.
    shiro-realm.iniプロファイル:カスタムreall情報をセキュリティマネージャに注入する
    
    [main]
    #    realm
    customRealm=cn.itcast.shiro.realm.CustomRealm
    # realm   securityManager,    spring   
    securityManager.realms=$customRealm
    
    
    
    

    前回はカスタムrealmを使用しましたが、doGetAuthenticationInfo()メソッドのみを書き換え、今回はdoGetAuthorizationInfo()メソッドを書き換えました
        //     
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(
                PrincipalCollection principals) {
            
            //  principals       
            // getPrimaryPrincipal             (    doGetAuthenticationInfo       SimpleAuthenticationInfo     ),
            String userCode =  (String) principals.getPrimaryPrincipal();
            
            //            
            //     ...
            //           
            List permissions = new ArrayList();
            permissions.add("user:create");//     
            permissions.add("items:add");//      
            //....
            
            //      ,      (       permissions)
            SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
            //             simpleAuthorizationInfo   
            simpleAuthorizationInfo.addStringPermissions(permissions);
    
            return simpleAuthorizationInfo;
        }
    

    試験手順:
    
        //    realm        
        @Test
        public void testAuthorizationCustomRealm() {
    
            //   SecurityManager  
            Factory factory = new IniSecurityManagerFactory(
                    "classpath:shiro-realm.ini");
            //   SecurityManager
            SecurityManager securityManager = factory.getInstance();
            //  SecurityManager         , spring  SecurityManager  spring   ,      
            SecurityUtils.setSecurityManager(securityManager);
            //   subject
            Subject subject = SecurityUtils.getSubject();
    
            //   token  
            UsernamePasswordToken token = new UsernamePasswordToken("zhangsan",
                    "111111");
            //     
            try {
                subject.login(token);
            } catch (AuthenticationException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
    
            System.out.println("    :" + subject.isAuthenticated());
            //          
    
            //        ,  isPermitted     CustomRealm            
            // isPermitted       ,  user:create:1   CustomRealm         
            boolean isPermitted = subject.isPermitted("user:create:1");
            System.out.println("      " + isPermitted);
    
            boolean isPermittedAll = subject.isPermittedAll("user:create:1",
                    "user:create");
            System.out.println("      " + isPermittedAll);
    
            //   check      ,            
            subject.checkPermission("items:add:1");
    
        }

    二、SpringとShiroの統合
    2.1 jarパッケージのインポート
  • shiro-webのjar、
  • shiro-spring jar
  • shiro-codeのjar
  • 2.2クイックスタート
    shiroもfilterでブロックします.filterブロック後にspringで構成されているfilterChainに操作権を渡す
    Webでxmlでfilterを構成する
    
    
        
        
            shiroFilter
            org.springframework.web.filter.DelegatingFilterProxy
            
            
                targetFilterLifecycle
                true
            
            
            
                targetBeanName
                shiroFilter
            
        
        
            shiroFilter
            /*
        

    アプリケーションでxmlでwebを構成する.xmlのfitlerはspringコンテナのbeanに対応します.
    
    
    
        
            
            
            
            
            
            
            
            
            
                
                    
                    
                
            
            
            
            
                
                    
                    /** = anon
                
            
        

    セキュリティマネージャの設定
    
    
    
                
    

    reamlの設定
    
    
    
    

    手順:
  • はwebにあります.xmlファイルでshiroを構成するフィルタ
  • 対応するSpringプロファイルに対応するfilterChain
  • を配置する.
  • セキュリティマネージャを構成し、カスタムrealm
  • を注入します.
  • カスタムreaml
  • を構成
    2.3静的資源はブロックしない
    springでフィルタチェーンを構成したとき、このようなコードを見つけました.
        
         /** = anon

    anonは実はshiroに内蔵されたフィルタで、上のコードはすべての匿名ユーザーがアクセスできることを意味しています.
    もちろん、後で他の情報を構成する必要があります.ページが正常に表示されるように、私たちの静的リソースは一般的にブロックされる必要はありません.
    次のように構成できます.
    
        
        /images/** = anon
        /js/** = anon
        /styles/** = anon

    三、初認識shiroフィルター
    annoフィルタの、shiroには他のフィルタがあることがわかりました.見てみましょう
    一般的なフィルターには、次のようなものがあります.
    anon:例/admins/**=anonはパラメータがなく、匿名で使用できることを示している.authc:例えば/admins/user/**=authcは認証(ログイン)が必要であることを示し、FormAuthenticationFilterはフォーム認証であり、パラメータpermsはない:例/admins/user/**=perms[user:add:*]、パラメータは複数書くことができ、複数の場合は引用符を付けなければならず、パラメータ間はカンマで分割され、例えば/admins/user/**=perms["user:add:*,user:modify:*"]であり、複数のパラメータがある場合は各パラメータが通過しなければならない.isPermitedAll()メソッドになりたい.user:例えば/admins/user/**=userにはパラメータがなく、ユーザーが存在しなければならないことを示し、アイデンティティ認証に合格したか、または私の認証に合格したことを覚えてアクセスすることができ、ログイン操作時にチェックしない
    3.1登録と退出
    次のように、FormAuthenticationFilterアクセラレータを使用して実現されます.
  • ユーザーが認証していない場合、loginurlに認証を要求します【上はすでに構成しました】、ユーザーIDとユーザーパスワードはloginurl
  • にデータを提出します.
  • FormAuthenticationFilterは、requestのusernameとpassword(2つのパラメータ名は構成可能)を取り出す
  • をブロックします.
  • FormAuthenticationFilter呼び出しrealmはtoken(usernameおよびpassword)
  • に送信される
  • realm認証時にusernameに基づいてユーザ情報を問い合わせる(userid、usercode、username、menusを含むActiveuserに格納される).
  • クエリーが見つからない場合、realmはnullを返し、FormAuthenticationFilterはrequestドメインにパラメータ(例外情報が記録されている)
  • を入力します.
  • がユーザーの情報を問い合わせると、FormAuthenticationFilterはrealmから返された情報とtokenのユーザー名とパスワードを自動的に比較します.間違っている場合は、例外を返します.

  • 3.1.1登録ページ
    FormAuthenticationFilterのユーザーIDとパスワードのinputのデフォルト値(usernameとpassword)のため、ページのアカウントとパスワードを変更するinputの名前はusernameとpasswordです
    
            
        

    3.1.2登録コードの実現
    以上、ユーザが認証していない場合、要求されたloginurlが認証され、ユーザIDのユーザパスワードがloginrulに送信されると述べた.
    loginurlにコミットすると、フォームフィルタはusernameとpasswordを自動的に解析してrealmを呼び出して認証します.最終的にrequestドメインオブジェクトにshiroLoginFailure認証情報を格納し、異常な情報を返す場合はloginに異常を投げ出せばよい
    
    
    //      , applicationContext-shiro.xml    loginurl  
        @RequestMapping("login")
        public String login(HttpServletRequest request)throws Exception{
            
            //       request         ,shiroLoginFailure  shiro        
            String exceptionClassName = (String) request.getAttribute("shiroLoginFailure");
            //  shiro          ,        
            if(exceptionClassName!=null){
                if (UnknownAccountException.class.getName().equals(exceptionClassName)) {
                    //          
                    throw new CustomException("     ");
                } else if (IncorrectCredentialsException.class.getName().equals(
                        exceptionClassName)) {
                    throw new CustomException("   /    ");
                } else if("randomCodeError".equals(exceptionClassName)){
                    throw new CustomException("      ");
                }else {
                    throw new Exception();//              
                }
            }
            //          (    ),shiro                 
            //      login  
            return "login";
        }

    資格認定フィルタの構成
    
        
            
            /images/** = anon
            /js/** = anon
            /styles/** = anon
    
            
            /** = authc
        
    

    3.2終了
    私たちが脱退を実現する必要はありません.脱退したurl(このurlは存在しなくてもいい)にアクセスし、LogoutFilterによってブロックされ、セッションをクリアします.
    アプリケーションでxml構成LogoutFilter:
    
            
            /logout.action = logout

    四、認証後の情報をページに表示する
    1、認証後のユーザメニューをトップページに表示する2、認証後のユーザの情報をヘッダーに表示する
    realmはデータベースからユーザ情報を照会し,SimpleAuthenticationInfoにユーザメニュー,usercode,usernameなどを設定する.
    
        //realm     ,          
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(
                AuthenticationToken token) throws AuthenticationException {
            
            // token             
            //     token      
            String userCode = (String) token.getPrincipal();
    
            //    :       userCode      
            SysUser sysUser = null;
            try {
                sysUser = sysService.findSysUserByUserCode(userCode);
            } catch (Exception e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
    
            //         null
            if(sysUser==null){//
                return null;
            }
            //          
            String password = sysUser.getPassword();
            
            // 
            String salt = sysUser.getSalt();
    
            //            AuthenticationInfo
            
            //activeUser        
            ActiveUser activeUser = new ActiveUser();
            
            activeUser.setUserid(sysUser.getId());
            activeUser.setUsercode(sysUser.getUsercode());
            activeUser.setUsername(sysUser.getUsername());
            //..
            
            //    id    
            List menus  = null;
            try {
                //  service     
                menus = sysService.findMenuListByUserId(sysUser.getId());
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            //         activeUser
            activeUser.setMenus(menus);
    
            // activeUser  simpleAuthenticationInfo
            SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(
                    activeUser, password,ByteSource.Util.bytes(salt), this.getName());
    
            return simpleAuthenticationInfo;
        }

    md 5とハッシュを使用したので、アダプタを構成します.
    
    
    
        
        
    
    
    
    
        
        
    

    トップページにジャンプするときは、ユーザの認証情報を取り出し、JSPに転送すればよい
    
        //    
        @RequestMapping("/first")
        public String first(Model model)throws Exception{
            
            // shiro session  activeUser
            Subject subject = SecurityUtils.getSubject();
            //     
            ActiveUser activeUser = (ActiveUser) subject.getPrincipal();
            //  model    
            model.addAttribute("activeUser", activeUser);
            
            return "/first";
        }

    五、まとめ
  • Shiroユーザー権限には3つの方法があります
  • プログラミング
  • 注記式
  • ラベル式
  • Shiroのrealmのデフォルトはプロファイルの情報を探して許可されています.私たちは一般的にrealmをデータベースに行って対応する情報をクエリーします.したがって、reaml
  • をカスタマイズする必要があります.
  • 全体として、認証と認可のプロセスはそれほど悪くありません.
  • SpringはShiroと統合されており、Shiroの実際の操作はフィルタによって行われています.Shiroは私たちに多くのフィルターを提供してくれました.
  • はwebにあります.xmlにShiroフィルタ
  • を配置する.
  • Shiroプロファイルでwebを使用する.xmlで構成されたフィルタ.

  • セキュリティマネージャクラスを構成し、カスタムreamlを構成し、reamlをセキュリティマネージャクラスに注入します.セキュリティマネージャをShiroファクトリに渡して管理します.
  • フィルタチェーンに静的リソースをブロックしないように設定します.
  • Shiroでフィルタを使用してユーザ認証を行います.
  • は、認証のための要求経路
  • を構成する.
  • プログラマが要求パスにアクセスすると、ShiroはFormAuthenticationFilterを使用してrealmを呼び出してユーザの情報
  • を取得する.
  • realmlはtokenを取得することができ、ユーザー名によってデータベースからユーザーの情報を取得し、ユーザーが存在しない場合null
  • を返す.
  • FormAuthenticationFilterはreamlから返されたデータを比較し、異なる場合は例外
  • を放出します.
  • 私たちのリクエストパスは、異常な投げ出しがあるかどうかを検出するために使用され、検証に使用されません.

  • shiroはまた、ユーザーを終了するブロッカーを提供しています.urlを構成すればいいです.
  • ユーザのデータを取得する必要がある場合は、SecurityUtils.getSubject()はエージェントを取得し,エージェントを介してアイデンティティ情報を取得する.

  • 文章に間違いがあれば指摘を歓迎し、みんなで交流します.微信で技術的な文章を読むことに慣れて、もっとJava資源を手に入れたい学生は、
    注目微信公衆番号:Java 3 y