1. 程式人生 > 其它 >shiro認證管理

shiro認證管理

技術標籤:資料庫shiro安全jwtjava

1、認證

  身份認證就是判斷一個使用者是否為合法使用者的處理過程。通過核對使用者輸入的使用者名稱和口令,判斷身份是否正確。

2、shiro中認證關鍵物件

  subject:主體

訪問系統的使用者,主體可以是使用者、程式等,進行認證都稱為主體。

  Principal:身份資訊

例如:是主體(subject)進行身份認證的標識,標識必須具有唯一性。一個主體可以有多個身份,例如可以用手機號、賬號、郵箱進行賬號密碼登陸。

  Credential:憑證資訊

口令,只有主體自己知道的安全資訊,例如,密碼,證書等。

3、認證流程

  登陸使用者,攜帶身份和口令(憑證),將兩種資訊

打包成一個令牌shirofilter進行攔截,將令牌拿到安全管理器中,呼叫認證器,認證器呼叫reaml獲取資料庫中資料,如果身份資訊與口令與原始資料中的存留資訊一致,就屬於認證成功,放行進入系統,否則失敗。

4、認證開發

4.1 引入依賴

<!--編碼處理  -->
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>
<!--JDk版本的引入  -->
    <profiles>
      <profile>
        <id>development</id>
        <activation>
          <jdk>1.8</jdk>
          <activeByDefault>true</activeByDefault>
        </activation>
        <properties>
          <maven.compiler.source>1.8</maven.compiler.source>
          <maven.compiler.target>1.8</maven.compiler.target>
          <maven.compiler.compilerVersion>1.8</maven.compiler.compilerVersion>
        </properties>
      </profile>
    </profiles>
<!--shiro包引入  -->
    <dependencies>
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.5.3</version>
        </dependency>
    </dependencies>

4.2 shiro.ini配置檔案

  在resource目錄下,該配置存放的本次認證的賬號和密碼。

[users]
zhangsan=123
lisi=456
wangwu=789

4.3 認證程式碼

package com.demo;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.subject.Subject;

public class ShiroDemo {
    public static void main(String[] args) {
        //建立安全管理器
        DefaultSecurityManager defaultSecurityManager=new DefaultSecurityManager();
        //建立realm  讀取配置檔案中的使用者名稱 密碼
        defaultSecurityManager.setRealm(new IniRealm("classpath:shiro.ini"));
        //使用工具,將安裝工具類中設定預設安全管理器
        SecurityUtils.setSecurityManager(defaultSecurityManager);
        //實用工具類獲取登入主體
        Subject subject = SecurityUtils.getSubject();
        //建立令牌  使用者名稱+密碼  
        UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "123");
        try {
            System.out.println("認證狀態:"+subject.isAuthenticated());
            subject.login(token);//使用者登入   這裡加入了使用者登陸資訊
            System.out.println("認證狀態:"+subject.isAuthenticated());  //驗證登陸資訊
            System.out.println("登入成功!!");
        } catch (UnknownAccountException e) {   
            e.printStackTrace();
            System.out.println("使用者名稱錯誤!!");
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            System.out.println("密碼錯誤!!!");
        }   
    }   
}

其他認證異常

  DisabledAccountException(賬號被禁用)

  LockedAccountException(賬號被鎖定)

  ExcessiveAttemptsException(登入失敗次數過多)

  ExpiredCredentialsException(憑證過期)

5、加鹽認證

md5工具,加入不同字串數字後密碼的強度

package com.demo.md5;

import org.apache.shiro.crypto.hash.Md5Hash;

/**
 * 三種組合的md5加密
 * @author Administrator
 *
 */
public class ShiroMD5 {
    public static void main(String[] args) {
        Md5Hash md5Hash=new Md5Hash("123");  //這個容易被反編譯  安全性不高
        System.out.println(md5Hash.toHex());
        //md5+salt  md5加密+自定義字串
        Md5Hash md5Hash2=new Md5Hash("123","x0*&p");
        System.out.println(md5Hash2.toHex());
        //md5+salt+hash雜湊
        Md5Hash md5Hash3=new Md5Hash("123","x0*&p",1024);
        System.out.println(md5Hash3.toHex());
    }
}

效果:

202cb962ac59075b964b07152d234b70
0ea1434575ac41da89b2335d8dde11e1
efe2cdcad63be25838e3847becd43df4   

  自定義CustomerRealm類中,需要繼承AuthorizingRealm類,進行登陸賬號、密碼、鹽salt的定義,當然真實情況,賬號密碼應該從資料庫中獲取。salt應該作為隨機字串變數存在。

package com.demo.md5;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

/**
 * 自定義md5+salt realm
 */
public class CustomerRealm extends AuthorizingRealm {
    //授權方法
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }
    //認證方法
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //獲取身份資訊
        String principal = (String) token.getPrincipal();
        //這裡的zhangsan就是資料查出來的,模擬   這裡的賬號、密碼按道理是在資料庫的變數
        if("zhangsan".equals(principal)){
            String password = "efe2cdcad63be25838e3847becd43df4";
            String salt = "x0*&p";    //自定義加鹽
            //資料庫的使用者名稱
            //資料庫md5+salt之後的密碼
            //註冊時的隨機鹽
            //realm的名字
            return new SimpleAuthenticationInfo(principal,password, 
                                                ByteSource.Util.bytes(salt),this.getName());
        }
        return null;
    }
}

測試類

package com.demo.md5;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;

public class TestAuthenticatorCusttomerRealm {
    public static void main(String[] args) {
        //建立securityManager
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        //IniRealm realm = new IniRealm("classpath:shiro.ini");
        //設定為自定義realm獲取認證資料
        CustomerRealm customerRealm = new CustomerRealm();
        //設定md5加密
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        credentialsMatcher.setHashAlgorithmName("MD5");  //新增加密字串
        credentialsMatcher.setHashIterations(1024);//設定雜湊次數   打亂順序
        customerRealm.setCredentialsMatcher(credentialsMatcher); //在customerRealm設定加密後的密碼驗證器//設定自定義realm
        defaultSecurityManager.setRealm(customerRealm);  //將自定義的realm設定到安全管理中
        //將安裝工具類中設定預設安全管理器
        SecurityUtils.setSecurityManager(defaultSecurityManager);  //將安全管理設定到安全工具中
        //獲取主體物件   
        Subject subject = SecurityUtils.getSubject();  
        //建立token令牌
        UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "123");
        try {
            //subject物件 中方法  +加鹽 +驗證+許可權操作
            subject.login(token);//使用者登入,shiro會自動將token中的password在自定義realm中加上鹽去處理
            System.out.println("登入成功~~");
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            System.out.println("使用者名稱錯誤!!");
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            System.out.println("密碼錯誤!!!");
        }
    }
}

6、授權認證

  CustomerRealm類中新增可放通的角色role,新增可訪問資源"user:*:01"。

package com.demo.grant;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
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 CustomerRealm extends AuthorizingRealm {
    //授權方法
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //獲取主要身份
        String primaryPrincipal = (String) principals.getPrimaryPrincipal();
        System.out.println("primaryPrincipal = " + primaryPrincipal);
        //根據身份資訊  使用者名稱   獲取當前使用者的角色資訊,以及許可權資訊   xiaochen admin  user
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        //將模擬資料庫中查詢角色資訊賦值給許可權物件
        simpleAuthorizationInfo.addRole("admin");
        simpleAuthorizationInfo.addRole("user");
        //將資料庫中查詢許可權資訊賦值給許可權物件
        //對使用者下01例項具有所有許可權   這是資源路徑例項
        simpleAuthorizationInfo.addStringPermission("user:*:01");
        //對product下一切資源例項具有建立許可權,*可以省略
        simpleAuthorizationInfo.addStringPermission("product:create");

        return simpleAuthorizationInfo;
    }

    //認證方法
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String principal = (String) token.getPrincipal();
        if("zhangsan".equals(principal)){
        //模擬資料庫中已經md5加鹽處理過的密碼 String password = "efe2cdcad63be25838e3847becd43df4"; String salt = "x0*&p"; //需要這個解開密碼 return new SimpleAuthenticationInfo(principal,password, ByteSource.Util.bytes(salt),this.getName()); } return null; } }

測試類

package com.demo.md5;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;

public class TestAuthenticatorCusttomerRealm {
    public static void main(String[] args) {
        //建立securityManager
        DefaultSecurityManager defaultSecurityManager = new DefaultSecurityManager();
        //IniRealm realm = new IniRealm("classpath:shiro.ini");
        //設定為自定義realm獲取認證資料
        CustomerRealm customerRealm = new CustomerRealm();
        //設定md5加密
        HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
        credentialsMatcher.setHashAlgorithmName("MD5");  //新增加密字串
        credentialsMatcher.setHashIterations(1024);//設定雜湊次數   打亂順序
        customerRealm.setCredentialsMatcher(credentialsMatcher); //MD5加密器//設定自定義realm
        defaultSecurityManager.setRealm(customerRealm);  //將自定義的realm設定到安全管理中
        //將安裝工具類中設定預設安全管理器
        SecurityUtils.setSecurityManager(defaultSecurityManager);  //將安全管理設定到安全工具中
        //獲取主體物件   
        Subject subject = SecurityUtils.getSubject();  
        //建立token令牌
        UsernamePasswordToken token = new UsernamePasswordToken("zhangsan", "123");
        try {
            //subject物件 中方法  +加鹽 +驗證+許可權操作 主體物件呼叫login方法
            subject.login(token);//使用者登入,shiro會自動將token中的password在自定義realm中加上鹽去處理
            System.out.println("登入成功~~");
        } catch (UnknownAccountException e) {
            e.printStackTrace();
            System.out.println("使用者名稱錯誤!!");
        }catch (IncorrectCredentialsException e){
            e.printStackTrace();
            System.out.println("密碼錯誤!!!");
        }

    }
}