问题起源
在前些天的文章中,我们了解到困惑了我们好几天的问题是由于jfinal新版中使用undertowserver方式启动,其嵌入filter的方式有变动,所以导致网上检索到的通过web.xml嵌入filter失败。
在不考虑修改undertowserver的情况下,也就意味着我们需要找到一种在undertowserver环境下,嵌入shiro的方式。
今天,我们就来尝试一种通过拦截器来实现的stateless jfinal 嵌入方式。
stateless的理解
个人对stateless的理解就是前后端分离,两次请求互相独立,通过约定的token等内容判断是否是同一个用户。
因此这要求,登录接口需要给用户生成一个随机的token,以便用户后续访问的时候带上。
登录接口
登录接口首先需要我们访问数据库,以及通过特定算法来验证用户名与密码是否匹配。如果匹配,则生成随机的字符串,即token,并保存在redis中,注意,映射关系是token为key,value为用户信息,可以是用户名,也可以是用户id等用户唯一标识。
@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("用户名与密码错误"); } }
另外,需要注意的有两点:
- 接口前调用@clear,即登录接口不应该被拦截验证
- 系统的登录接口,与shiro中的subject.login应该注意区分,是两个不同的概念。
自定义拦截器
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("权限错误:", e); try { throw e; } catch (throwable throwable) { throwable.printstacktrace(); } } } /** * 未授权处理 * * @param controller controller */ private void doprocessuunauthorization(controller controller) { controller.redirect("/login/nologin"); } }
上面的代码很长,我们重点看其中的这几行:
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,若不为空,将其转换为jwttoken对象,然后调用shiro的登录接口:s.login(jwttoken)
。
而shiro的login方法会触发自定义realm中的验证接口:
/** * 自定义认证 */ @override protected authenticationinfo dogetauthenticationinfo(authenticationtoken auth) throws authenticationexception { string token = (string) auth.getcredentials(); // 解密获得username,用于和数据库进行对比 string username = jwtutils.getusername(token); if (username == null || username == "") { throw new authenticationexception("token 校验失败"); } return new simpleauthenticationinfo(token, token, getname()); }
其中,jwtutils。getusername的具体代码如下,和设置token是对应的:
/** * @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的嵌入。
遗留问题
目前欠缺的一个问题是,不能实现shiro的注解来进行权限验证,这个问题我们还准备借助shiroplugin来实现,由于jfinal已经升级到4.8了,而shiroplugin目前还停留在支持jfinal 3.x的版本,所以需要我们下载jfianl-shiro-plugin源码做一些修改。
到此这篇关于jfinal中stateless模式嵌入shiro验证的实现方式的文章就介绍到这了,更多相关jfinal shiro验证内容请搜索<计算机技术网(www.ctvol.com)!!>以前的文章或继续浏览下面的相关文章希望大家以后多多支持<计算机技术网(www.ctvol.com)!!>!
需要了解更多c/c++开发分享jfinal中stateless模式嵌入shiro验证的实现方式,都可以关注C/C++技术分享栏目—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/1237701.html