シオが小さく美しい安全の枠組み

14092 ワード

最近のプロジェクトはshiroを利用して権限管理を行う必要があります。本人も初めて接触しました。まずshiroはjavaのセキュリティフレームです。登録認証、権限認証など他の機能を実現してくれます。主な注意点は以下の通りです。
  • Subject:現在のユーザ
  • と見なすことができる。
  • Token:トークンは、現在のユーザがフォームを利用して送信しているユーザ名とパスワード情報
  • を含む。
  • Authentication:アイデンティティ認証は、現在のユーザ名とパスワード認証
  • として理解できる。
  • Authorzation:権限認証は、現在のユーザがあるリソースにアクセスしているときの権限判断
  • であると理解できる。
  • Realm:セキュリティデータソースは、現在のユーザに関するアイデンティティ情報および権限関連情報(しばらくはこのように理解できる)
  • として理解できる。
    全体構成は大体次の通りです。
    How shiroに関するdependenciesは大体次の通りです。(特にここではページテンプレートエンジンはJspではなくThymeleafを使います。)
            
            <dependency>  
                <groupId>org.apache.shirogroupId>  
                <artifactId>shiro-coreartifactId>  
                <version>1.2.2version>  
            dependency> 
            
            <dependency>  
            <groupId>org.apache.shirogroupId>  
                <artifactId>shiro-webartifactId>  
                <version>1.2.2version>  
            dependency>
            
             <dependency>
                <groupId>org.apache.shirogroupId>
                <artifactId>shiro-springartifactId>
                <version>1.2.2version>
            dependency>
            
            
            <dependency>
                <groupId>com.github.theborakompanionigroupId>
                <artifactId>thymeleaf-extras-shiroartifactId>
                <version>2.0.0version>
            dependency>
      dependencies>
    shiro関連の依存性を追加するには、springのプロファイルに次のような構成を追加する必要があります。
            
            <bean id="userRealm" class="com.myjava.realm.UserRealm">
                <property name="credentialsMatcher" ref="credentialsMatcher">property>
            bean>
            
            <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
                <property name="realm" ref="userRealm"/>
                
                <property name="sessionManager" ref="defaultWebSessionManager"/>
                <property name="rememberMeManager" ref="remembermeManager"/>
            bean>
            
            <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
                
                <property name="hashAlgorithmName" value="md5"/>
                <property name="hashIterations" value="2">property>
            bean>
    
              
            <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">  
                <property name="staticMethod"   
                    value="org.apache.shiro.SecurityUtils.setSecurityManager"/>  
                <property name="arguments" ref="securityManager"/>  
            bean>  
              
            <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>  
    まず登録から始めて、実はshiroの中のデフォルトのフィルタはすでに登録から身分認証までを実現してくれました。私たちはshiroの配置ファイルにフィルタを配置すればいいです。しかし、ここではこの過程をよりよく知るために、まず自分で登録したControllerを書いてください。
    @RequestMapping("/login")
    public String login(User user, ModelMap mm , HttpSession session,HttpServletResponse response,RedirectAttributes attrs ) {
            UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername() , user.getPassword()) ;
            //rememberMe
            token.setRememberMe(true);
            //    
            Subject subject = SecurityUtils.getSubject() ;
            try {
                //  
                subject.login(token);
            } catch (AuthenticationException e) {
                System.out.println("---------------         -------------------");
                attrs.addFlashAttribute("msg","        ") ;
                e.printStackTrace();
                return "redirect:toLogin.action" ;
            }
            subject.getSession().setAttribute("user", userService.getByUserName(user.getUsername()));
            return "redirect:index.action";
        }
    ユーザーが入力したusernameおよびpasswordはデータベース内の情報を利用して対比する必要があるため、これは必然的にデータベースのインタラクションに関連し、shiroはこのインタラクションをRealmにカプセル化し、つまりshiroはRealmを通じて情報を取得し、realmは本当にデータベースから情報を取得する。だから私達はRealmをカスタマイズしたいです。
    public class UserRealm extends AuthorizingRealm{
        @Autowired
        private RoleService roleService  ;
        @Autowired
        private UserService userService ;
        @Autowired
        private PermissionService permissionService ;
        //           
        private SimpleAuthorizationInfo info = new SimpleAuthorizationInfo() ;
        /**
         *         
         */
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
            String username = (String) principals.getPrimaryPrincipal();
            /**
             *          SimplAuthorizationInfo
             */
            info.setRoles(this.addRoles(username));
            /**
             *          SimpleAuthorizationInfo 
             */
            info.setStringPermissions(this.addPermissions(username));
    
            return info;
        }
        /**
         *         
         * CredentialsMatcher       
         */
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(
                AuthenticationToken token) throws AuthenticationException {
            //           
            String username = (String) token.getPrincipal() ;
            //      user
            User accountUser = userService.getByUserName(username) ;
            //  
            if(accountUser == null) throw new UnknownAccountException() ;
            //   credentialMatcher      
            return new SimpleAuthenticationInfo(accountUser.getUsername(),accountUser.getPassword(),new SimpleByteSource(accountUser.getSalt()),getName());
        }
    上記のoverrideの2つの方法に注意してください。doGetAuthentication Infoはユーザ認証情報を取得し、doGetAuthortionInfoはユーザ権限情報を取得するものです。実行フローは以下の通りである。1.フォームから送信されたユーザ情報をUsernamePasswordTokenにカプセル化する。2.Subject subject = SecurityUtils.getSubject() ;を介してsubject本体を取得する。3.登録挙動subject.login(token);を実行した後、securityManagerに本物のlogin操作を実行するように依頼します。securityManagerこそが本当のコアです。4.shiroは、設定されたRealmを自動的に取得します。上でカスタマイズされたUserRealmのように、Realmで現在のusernameに対応するユーザ関連情報(username、passwordなど)5.内部で呼び出し前に配置されたHashedCredentialsMatchパスワードマッチング器を取得してパスワード検証します。マッチングが失敗したらIncorectCredentialsExceptionを投げます。
    ログインが成功するとsubject.isAuthenticated()はreturn trueになります。これで登録の雛形が完成します。
    次号に続く…