shiro權限認證及受權的執行流程

《一,認證》數據庫

1.先建兩個class文件session

   一個寫 AuthRealm (受權與認證方法,並繼承) extends AuthorizingRealm  app

獲取其默認方法doGetAuthorizationInfo(受權方法) doGetAuthenticationInfo(認證方法) jsp

                 一個寫PasswordMatcher(密碼驗證器,並繼承) extends SimpleCredentialsMatcheride

獲取默認方法doCredentialsMatch 工具

2.在Action的登陸方法中 ui

         @Action("loginAction_login")//重頁面跳轉過來的路徑名加密

         public String login() throws Exception {對象

             //判斷用戶名是否是爲空,若是是說明沒有登陸,跳轉到用戶登陸頁面blog

             if(UtilFuns.isEmpty(username)){

                    return "login";

             }

//1.SecurityUtils:是shiro的一個工具類。經過SecurityUtils獲取getSubject 獲得一個返回值

             Subject subject = SecurityUtils.getSubject();

//3.根據邏輯2。new一個 UsernamePasswordToken,並傳上用戶名及密碼。把返回值傳給登入做爲條件。

             UsernamePasswordToken token = new UsernamePasswordToken(username,password);

             

             try {

//2. subject的返回值裏有兩個方法logout:登出 login:登入。這裏咱們使用登陸方法,經過方法咱們能夠看到須要一個返回值:AuthenticationToken的類型,又由於AuthenticationToken  是一個接口,因此咱們使用他下面的UsernamePasswordToken 的實現類來寫(ps:查看方法:Ctrl+t),

                    subject.login(token);//當調用subject的登入方法時,會跳轉到認證的方法上。。。。。。。。。。

 

//4.在證方法中subject已經把獲取到了用戶,因此咱們用subject.getPrincipal 能夠獲取到登陸的用戶,Principal:他是在認證方法中的principal:主要對象(登陸的用戶,詳情看認證方法return的哪一步註釋)

                    User user = (User) subject.getPrincipal();

//5.把user用戶數據經過Session.put放在session值棧中。SysConstant.CURRENT_USER_INFO:是一個返回的值,在jsp頁面中能夠接收到,也能夠直接寫一個字符串讓頁面接收,返回的數據能夠在頁面作回顯等功能

                    session.put(SysConstant.CURRENT_USER_INFO, user);

                    return SUCCESS;//以上所有都過了後,讓其訪問頁面數據

             } catch (Exception e) {

                    // TODO Auto-generated catch block

                    e.printStackTrace();

                    super.put("errorInfo", "您的用戶名或密碼錯誤"); //登陸頁面的錯誤信息提示

                    return "login";

             }

       }

       

       

       //退出

       @Action("loginAction_logout")

       public String logout(){

             session.remove(SysConstant.CURRENT_USER_INFO);       //刪除session

             SecurityUtils.getSubject().logout();   //調用登出方法

             return "logout";

       }

3.在認證方法中的doGetAuthenticationInfo

            protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {

             // TODO Auto-generated method stub

             System.out.println("調用認證方法");

             UsernamePasswordToken token =(UsernamePasswordToken)arg0;//先將arg0強轉爲UsernamePasswordToken類型

             final String username = token.getUsername();//經過token獲取到用戶名

             Specification<User> spec = new Specification<User>() {   //把username 設爲查詢條件,查詢數據庫是否有這個用戶名

                    @Override

                    public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {

                           // TODO Auto-generated method stub

                           return cb.equal(root.get("username").as(String.class),username);

                    }

             };

             List<User> find = userServiceimpl.find(spec); //把spec 條件放到 查詢中查詢數據  查詢用戶名

             if(find!=null&& find.size()>0){  //判斷返回的結果不爲空,及返回的數不小於0

                    User user = find.get(0); //經過索引獲取到返回值的第一個數中的數據

                    return new SimpleAuthenticationInfo(user, user.getPassword(), getName()) ;//這裏若是上面的都成立後會return到密碼校驗哪裏去

  /*   SimpleAuthenticationInfo:是doGetAuthenticationInfo的一個實現類,由於doGetAuthenticationInfo 是一個接口不能直接new  

       把返回值添加到條件中 //principal:主要對象(登陸的用戶) , credentials:密碼 ,realm的名字能夠經過getName獲取類名做爲區分 */

             }

             return null;

       }

 

4.在密碼檢驗中PasswordMatcher  

public class PasswordMatcher extends SimpleCredentialsMatcher {  //先實現一個接口SimpleCredentialsMatcher  獲取doCredentialsMatch的內部方法

       @Override

       public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {

             

             System.out.println("調用了密碼對比器");

             UsernamePasswordToken utoken = (UsernamePasswordToken) token; 

           /*[把AuthenticationToken 中的token 裝換爲AuthenticationToken 中的(ps:查看方法Ctrl+t)

           UsernamePasswordToken實現類 由於AuthenticationToken 是接口不能new數據],*/

             

             String pwd = new String(utoken.getPassword());//經過utoken 獲取用戶密碼,並轉換成String類型,注意這裏的轉換不能強轉,要用new的方法

             //source:要加密的內容   salt:增長複雜度的內容  哈希次數:2

             Md5Hash md5Hash = new Md5Hash(pwd, utoken.getUsername(), 2);  //調用Md5加密 爲輸入的數據加密

             String credentials = (String)info.getCredentials();  //經過AuthenticationInfo 的info 查詢數據庫的密碼 裝換成String類型

             return equals(md5Hash.toString(),credentials); //對比用戶輸入的數據和數據庫密碼是否一致。return走,返回到Action方法中。

       }

}

 

5.執行流程圖

《二,受權》

1.在受權方法中

@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {    System.out.println("受權");        SimpleAuthorizationInfo simpleAuthorizationInfo=new SimpleAuthorizationInfo();    Set<String> permissionSet = new HashSet<>();    Set<String> roleNameSet = new HashSet<>();    ShiroUser shiroUser = (ShiroUser) principalCollection.getPrimaryPrincipal();    List<Integer> roleList = shiroUser.getRoleList();    for (Integer roleId : roleList) {        List<String> permissions = roleMenuMapper.findPermissionsByRoleId(roleId);        if (permissions != null) {            for (String permission : permissions) {                if (StringUtils.isNotEmpty(permission)) {                    permissionSet.add(permission);                }            }        }        String roleName = roleMapper.findRoleNameByRoleId(roleId);        roleNameSet.add(roleName);    }    simpleAuthorizationInfo.addStringPermissions(permissionSet);    simpleAuthorizationInfo.addRoles(roleNameSet);    //查詢登陸用戶的全部角色的權限    return simpleAuthorizationInfo;}
相關文章
相關標籤/搜索