Spring整合Shiro(二)

前面一個小節完成基本的配置,後面一個小節重點放在認證(登陸)和授權

  • UserHandler.java
package cn.zzu.wcj.shiro.handler;

import javax.servlet.http.HttpSession;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import cn.zzu.wcj.shiro.service.ShiroService;

@Controller
@RequestMapping("/Shiro")
public class UserHandler {

    @Autowired
    private ShiroService shiroService  ;

    @RequestMapping("doLogin")
     public String doLogin(@RequestParam String userName,@RequestParam String password){
            Subject currentUser = SecurityUtils.getSubject();
            System.out.println(userName+"###############"+password);
            if (!currentUser.isAuthenticated()) {
                //把用戶賬號和密碼封裝成令牌
                UsernamePasswordToken token = new UsernamePasswordToken(userName, password);
                System.out.println("############1.Token"+token.hashCode());
                //設置記住我
                token.setRememberMe(true);
                try {
                    //執行登陸
                    currentUser.login(token);
                //若賬戶不存在,則Shiro會拋出UnknownAccountException異常
                } catch (UnknownAccountException uae) {
                    System.out.println("##############用戶名錯誤!"+uae);
                //若賬戶存在,但密碼不存在,則拋出IncorrectCredentialsException異常               
                } catch (IncorrectCredentialsException ice) {
                    System.out.println("##############密碼錯誤!"+ice);
                //若賬戶被鎖定,就拋出LockedAccountException異常                
                } catch (LockedAccountException lae) {
                    System.out.println("##############賬戶鎖定!"+lae);

                //所有認證時異常的父類
                }catch (AuthenticationException ae) {
                    System.out.println("##############登陸錯誤!"+ae);
                }catch(Exception e){
                     System.out.println("##################"+e);
                }
            }
            return "redirect:/list.jsp" ;
    }

    @RequestMapping("/testAnno")
    public String testAnno(HttpSession session){
            session.setAttribute("wcj","java");
            this.shiroService.sayHello(); 
            return "redirect:/list.jsp"  ;
    }

}
  • ShiroRealm.java
package cn.zzu.wcj.shiro.realm;

import java.util.Arrays;

import java.util.HashSet;
import java.util.Set;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
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 org.apache.shiro.util.ByteSource;

public class ShiroRealm extends AuthorizingRealm {


    /**
     * @see 授權會被 shiro 回調的方法
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(
            PrincipalCollection principals) {
        System.out.println("#################################################授權回調");
        //1. 從 PrincipalCollection 中來獲取登錄用戶的信息
        Object userName=principals.getPrimaryPrincipal()  ;
        //2. 利用登錄的用戶的信息來用戶當前用戶的角色或權限(可能需要查詢數據庫)
        Set<String> roles=new HashSet<String>()  ;  
        roles.addAll(Arrays.asList("user"))  ;
        //3. 創建 SimpleAuthorizationInfo, 並設置其 reles 屬性.
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo(roles)  ;
        return info  ;
    }

    /**
     * @see 此方法是用來完成認證(即登陸功能的)
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken token) throws AuthenticationException {
         System.out.println("############[UsernamePasswordRealm]2.Token"+token);
         SimpleAuthenticationInfo authcInfo=null ;
         //1.將AuthenticationToken強轉成UsernamePasswordToken
         UsernamePasswordToken upToken=(UsernamePasswordToken) token;
         //2.獲取用戶名
         String userName=upToken.getUsername()  ;
         //3.與數據庫中用戶名進行比對
         if("unknow".equals(userName)){
              throw new UnknownAccountException("用戶名不存在")  ;   //拋出用戶名錯誤異常
         }
         if("ghost".equals(userName)){
             throw new LockedAccountException("用戶被鎖定")   ;
         }
         //4.將數據庫中查詢到的用戶名和密碼放置到SimpleAuthenticationInfo中
         //1)Object principal 用戶認證信息,即用戶名, 
         //2)Object credentials 用戶密碼, 
         //3)String realmName Real名稱,通過getName取得
         Object principal="admin"   ;
         Object credentials="02bad5ac06ea6ce0be3a24fd39781d11"  ;
         String realmName=super.getName()   ;           //調用父類獲取Realm名稱的方法
         ByteSource credentialsSalt=ByteSource.Util.bytes(userName);  //鹽值加密
         authcInfo=new SimpleAuthenticationInfo(principal, credentials, credentialsSalt, realmName);
         return authcInfo;
    }

}
  • ShiroService.java
package cn.zzu.wcj.shiro.service;

import java.util.Date;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.session.Session;
import org.springframework.stereotype.Service;

@Service
public class ShiroService {

    @RequiresRoles(value={"admin","user"},logical=Logical.OR)
    public void sayHello(){
        System.out.println("Hello World !!! "+new Date());
        Session session = SecurityUtils.getSubject().getSession();
        System.out.println("############wcj-->"+session.getAttribute("wcj"));
    }

}

Tips:上面的這些代碼看懂了就可以快速搭建Shiro安全框架,你看不懂並不代表我看不懂,我粘貼一下就可以在項目中跑起來,OK?想學習就不要浮躁

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章