【Shiro】Shiro從小白到大神(五)-自定義Realm

用數據庫的話,至少會涉及到這幾張表:
用戶表,角色表,權限表

角色和用戶是一對多的關係 多個用戶可以擁有同一個角色
角色和權限在這裏也是一對多的關係 一個角色可以擁有很多個權限

數據庫表名:
t_role 角色表
並插入如下數據

t_user 用戶表
roleId關聯角色表

t_permission 權限表
roleId關聯角色表

接下來就是設置外鍵,設置好之後就看架構設計:

接下來就是寫代碼了,首先肯定是寫一個連接數據庫的工具類:
DbUtils.java

package cn.chenhaoxiang.common;


import java.sql.Connection;
import java.sql.DriverManager;

/**
 * 數據庫工具類
 * @author chenhaoxiang
 *
 */
public class DbUtils {

    /**
     * 獲取數據庫連接
     * @return
     * @throws Exception
     */
    public Connection getCon() throws Exception{
        Class.forName("com.mysql.jdbc.Driver");
        Connection con=DriverManager.getConnection("jdbc:mysql://localhost:3306/db_shiro", "root", "1234");
        return con;
    }

    /**
     * 關閉數據庫連接
     * @param con
     * @throws Exception
     */
    public void closeCon(Connection con)throws Exception{
        if(con!=null){
            con.close();
        }
    }

    public static void main(String[] args) {
        DbUtils dbUtil=new DbUtils();
        try {
            dbUtil.getCon();
            System.out.println("數據庫連接成功");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            System.out.println("數據庫連接失敗");
        }
    }
}

既然連接數據庫,肯定就需要用到數據庫的驅動包,在maven中導入mysql驅動包。

        <!--MySQL驅動-->
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.40</version>
        </dependency>

版本不同的可以自行去Maven中央倉庫去進行搜索。

你的連接賬號密碼可能與我的不同,記得修改。
完成之後測試一波,沒問題的話我們繼續

接下來寫一個自定義的Realm:

package cn.chenhaoxiang.realm;

import cn.chenhaoxiang.common.DbUtils;
import cn.chenhaoxiang.dao.UserDao;
import cn.chenhaoxiang.entity.User;
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 java.sql.Connection;

/**
 * 繼承一個認證的Realm
 * @author chenhaoxiang
 */
public class MyRealm extends AuthorizingRealm{

    private UserDao userDao = new UserDao();
    private DbUtils dbUtils = new DbUtils();
    /**
     * 爲當前登錄成功的用戶授予角色和權限,從數據庫讀取
     * 如果登錄失敗,不會到這裏來的
     * @param principalCollection
     * @return
     */
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //登錄成功之後
        String userName = (String) principalCollection.getPrimaryPrincipal();//獲取用戶信息
        //認證信息
        SimpleAuthorizationInfo simpleAuthenticationInfo = new SimpleAuthorizationInfo();
        Connection con = null;
        try{
            con = dbUtils.getCon();
            simpleAuthenticationInfo.setRoles(userDao.getRoles(con,userName));//設置角色
            simpleAuthenticationInfo.setStringPermissions(userDao.getPermissions(con,userName));//獲取權限
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                dbUtils.closeCon(con);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return simpleAuthenticationInfo;
    }

    /**
     * 獲取認證信息  驗證當前登錄的用戶
     * @param token
     * @return 登錄失敗返回null
     * @throws AuthenticationException
     */
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String userName = (String) token.getPrincipal();//獲取用戶名
        //通過用戶名去數據庫查找信息 然後和提交過來的信息比對
        Connection con = null;
        try{
            con = dbUtils.getCon();
            User user = userDao.getByUserName(con,userName);
            if(user!=null){
                AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user.getUserName(),user.getPassword(),"aa");//第二個參數密碼是數據庫的密碼,第三個參數realmName,我們在這裏隨便寫一個
                return authenticationInfo;//shiro內部會幫我們比對的
            }
            return null;
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                dbUtils.closeCon(con);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

}

其他還有一些類,大家直接來我們的github下載完整示例吧。
數據庫的腳本在項目的WEB-INF的sql文件夾內

演示的話,大家可以先進入登錄頁面,然後登錄來進行測試、
可以在登錄驗證的MyRealm類中設置斷點,這樣會讓你記憶深一些,也會容易理解一些,理一下驗證的順序。

源代碼下載地址:

GITHUB源碼下載地址:點我進行下載

本文章由[諳憶]編寫, 所有權利保留。
歡迎轉載,分享是進步的源泉。

轉載請註明出處:http://chenhaoxiang.cn/2017/12/12/2143/

本文源自諳憶的博客

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