最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

jfinal中stateless模式嵌入shiro驗(yàn)證的實(shí)現(xiàn)方式

 更新時(shí)間:2022年06月24日 14:26:25   作者:KevinQ  
這篇文章主要介紹了jfinal中stateless模式嵌入shiro驗(yàn)證,今天,我們就來嘗試一種通過攔截器來實(shí)現(xiàn)的Stateless Jfinal嵌入方式,需要的朋友可以參考下

問題起源

在前些天的文章中,我們了解到困惑了我們好幾天的問題是由于jfinal新版中使用undertowServer方式啟動(dòng),其嵌入filter的方式有變動(dòng),所以導(dǎo)致網(wǎng)上檢索到的通過web.xml嵌入filter失敗。

在不考慮修改undertowServer的情況下,也就意味著我們需要找到一種在undertowServer環(huán)境下,嵌入shiro的方式。

今天,我們就來嘗試一種通過攔截器來實(shí)現(xiàn)的Stateless Jfinal 嵌入方式。

Stateless的理解

個(gè)人對Stateless的理解就是前后端分離,兩次請求互相獨(dú)立,通過約定的token等內(nèi)容判斷是否是同一個(gè)用戶。

因此這要求,登錄接口需要給用戶生成一個(gè)隨機(jī)的token,以便用戶后續(xù)訪問的時(shí)候帶上。

登錄接口

登錄接口首先需要我們訪問數(shù)據(jù)庫,以及通過特定算法來驗(yàn)證用戶名與密碼是否匹配。如果匹配,則生成隨機(jī)的字符串,即token,并保存在redis中,注意,映射關(guān)系是token為key,value為用戶信息,可以是用戶名,也可以是用戶id等用戶唯一標(biāo)識(shí)。

@Clear
public void Login() {
    String name = getPara("name");
    String password = getPara("password");
    if ("admin".equals(name)) { // TODO 判斷密碼與用戶名是否正確
        Cache cache = Redis.use();
        String token = StrKit.getRandomUUID();
        cache.set("TOKEN:" + token, name);
        renderText(token);
    } else {
        renderText("用戶名與密碼錯(cuò)誤");
    }
}

另外,需要注意的有兩點(diǎn):

  • 接口前調(diào)用@Clear,即登錄接口不應(yīng)該被攔截驗(yàn)證
  • 系統(tǒng)的登錄接口,與shiro中的subject.login應(yīng)該注意區(qū)分,是兩個(gè)不同的概念。

自定義攔截器

package com.holdoa.core.interceptor;
import com.holdoa.core.controller.BaseController;
import com.holdoa.core.filter.JWTToken;
import com.jfinal.aop.Interceptor;
import com.jfinal.aop.Invocation;
import com.jfinal.core.Controller;
import com.jfinal.kit.LogKit;
import com.jfinal.kit.StrKit;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.aop.MethodInvocation;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.authz.aop.AnnotationsAuthorizingMethodInterceptor;
import org.apache.shiro.subject.Subject;
import java.lang.reflect.Method;
public class MyShiroInterceptor extends AnnotationsAuthorizingMethodInterceptor implements Interceptor {
	 
    public MyShiroInterceptor() {
        getMethodInterceptors();
    }
 
    public void intercept(final Invocation inv) {
        try {
            String token = inv.getController().getHeader("token");
            if (StrKit.isBlank(token)) {
                BaseController b = (BaseController) inv.getController();
                b.renderAppError("缺少token");
                return;
            } else {
                Subject s = SecurityUtils.getSubject();
                JWTToken jwtToken = new JWTToken(token);
                s.login(jwtToken);
                inv.invoke();
            }
        } catch (Throwable e) {
            if (e instanceof AuthorizationException) {
                doProcessuUnauthorization(inv.getController());
            }
            LogKit.warn("權(quán)限錯(cuò)誤:", e);
            try {
                throw e;
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
        }
    }
 
    /**
     * 未授權(quán)處理
     *
     * @param controller controller
     */
    private void doProcessuUnauthorization(Controller controller) {
        controller.redirect("/login/noLogin");
    }
}

上面的代碼很長,我們重點(diǎn)看其中的這幾行:

String token = inv.getController().getHeader("token");
if (StrKit.isBlank(token)) {
    BaseController b = (BaseController) inv.getController();
    b.renderAppError("缺少token");
    return;
} else {
    Subject s = SecurityUtils.getSubject();
    JWTToken jwtToken = new JWTToken(token);
    s.login(jwtToken);
    inv.invoke();
}

邏輯可以描述為:獲取token,若不為空,將其轉(zhuǎn)換為JWTToken對象,然后調(diào)用shiro的登錄接口:s.login(jwtToken)。

而shiro的login方法會(huì)觸發(fā)自定義Realm中的驗(yàn)證接口:

/**
	 * 自定義認(rèn)證
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken auth) throws AuthenticationException {
		String token = (String) auth.getCredentials();
		 // 解密獲得username,用于和數(shù)據(jù)庫進(jìn)行對比
        String userName = JwtUtils.getUsername(token);
        if (userName == null || userName == "") {
            throw new AuthenticationException("token 校驗(yàn)失敗");
        }
		return new SimpleAuthenticationInfo(token, token, getName());
	}

其中,JwtUtils。getUsername的具體代碼如下,和設(shè)置token是對應(yīng)的:

/**
     * @return token中包含的用戶名
     */
    public static String getUsername(String token) {
		Cache cache = Redis.use();
		String username = (String)cache.get(RedisKeyPreFix.NEW_OA_MANAGE_TOKEN_PREFIX + token);
		return username;
    }

如此,便做到了shiro的嵌入。

遺留問題

目前欠缺的一個(gè)問題是,不能實(shí)現(xiàn)shiro的注解來進(jìn)行權(quán)限驗(yàn)證,這個(gè)問題我們還準(zhǔn)備借助ShiroPlugin來實(shí)現(xiàn),由于jfinal已經(jīng)升級到4.8了,而shiroPlugin目前還停留在支持jfinal 3.x的版本,所以需要我們下載jfianl-shiro-plugin源碼做一些修改。

到此這篇關(guān)于jfinal中stateless模式嵌入shiro驗(yàn)證的實(shí)現(xiàn)方式的文章就介紹到這了,更多相關(guān)jfinal shiro驗(yàn)證內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

南安市| 蓝田县| 赫章县| 古丈县| 汤阴县| 股票| 资兴市| 新巴尔虎左旗| 潍坊市| 庆元县| 赤水市| 新和县| 崇左市| 杨浦区| 乌兰浩特市| 甘孜| 饶河县| 樟树市| 永昌县| 永安市| 武宣县| 会昌县| 泊头市| 北票市| 木兰县| 武川县| 山阴县| 城固县| 咸宁市| 秭归县| 竹溪县| 三穗县| 宜宾县| 建湖县| 东兴市| 滕州市| 永宁县| 蓬溪县| 敦化市| 合川市| 邵阳县|