jfinal中stateless模式嵌入shiro验证的实现方式

目录
  • 问题起源
  • Stateless的理解
  • 登录接口
  • 自定义拦截器
  • 遗留问题

问题起源

在前些天的文章中,我们了解到困惑了我们好几天的问题是由于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验证内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • springboot整合shiro多验证登录功能的实现(账号密码登录和使用手机验证码登录)

    1. 首先新建一个shiroConfig shiro的配置类,代码如下: @Configuration public class SpringShiroConfig { /** * @param realms 这儿使用接口集合是为了实现多验证登录时使用的 * @return */ @Bean public SecurityManager securityManager(Collection<Realm> realms) { DefaultWebSecurityManager sManager

  • spring boot 集成 shiro 自定义密码验证 自定义freemarker标签根据权限渲染不同页面(推荐

    项目里一直用的是 spring-security ,不得不说,spring-security 真是东西太多了,学习难度太大(可能我比较菜),这篇博客来总结一下折腾shiro的成果,分享给大家,强烈推荐shiro,真心简单 : ) 引入依赖 <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4

  • Java中SSM+Shiro系统登录验证码的实现方法

     先给大家展示下效果图: 1.验证码生成类: import java.util.Random; import java.awt.image.BufferedImage; import java.awt.Graphics; import java.awt.Font; import java.awt.Color; /** * 验证码生成器类,可生成数字.大写.小写字母及三者混合类型的验证码. 支持自定义验证码字符数量: 支持自定义验证码图片的大小: 支持自定义需排除的特殊字符: * 支持自定义干扰线

  • jfinal添加jcaptcha验证码实现方法

    复制代码 代码如下: package com.g.core.common.JCaptcha; import java.awt.Color;import java.awt.Font; import com.octo.captcha.component.image.backgroundgenerator.BackgroundGenerator;import com.octo.captcha.component.image.backgroundgenerator.FileReaderRandomBac

  • jfinal中stateless模式嵌入shiro验证的实现方式

    目录 问题起源 Stateless的理解 登录接口 自定义拦截器 遗留问题 问题起源 在前些天的文章中,我们了解到困惑了我们好几天的问题是由于jfinal新版中使用undertowServer方式启动,其嵌入filter的方式有变动,所以导致网上检索到的通过web.xml嵌入filter失败. 在不考虑修改undertowServer的情况下,也就意味着我们需要找到一种在undertowServer环境下,嵌入shiro的方式. 今天,我们就来尝试一种通过拦截器来实现的Stateless Jfi

  • iOS中使用正则表达式NSRegularExpression 来验证textfiled输入的内容

    何谓正则表达式 正则表达式(regular expression),在计算机科学中,是指一个用来描述或者匹配一系列符合某个句法规则的字符串的单个字符串.在很多文本编辑器或其他工具里,正则表达式通常被用来检索和/或替换那些符合某个模式的文本内容.正则表达式这个概念最初是由Unix中的工具软件(例如sed和grep)普及开的.正则表达式通常缩写成"regex",单数有regexp.regex,复数有regexps.regexes.regexen. 正则表达式组成 正则表达式有两种类型的字符

  • javascript设计模式--策略模式之输入验证

    策略模式定义了算法家族,分别封装起来,让他们之间可以互相替换,此模式让算法的变化独立于使用算饭的客户. 先定义一个简单的输入表单: <!DOCTYPE html> <html> <head> <meta charset="utf-"> <style> .form{ width: px; height: px; #margin: px auto; } .form-item-label{ width:px; text-align:

  • 踩坑:pytorch中eval模式下结果远差于train模式介绍

    首先,eval模式和train模式得到不同的结果是正常的.我的模型中,eval模式和train模式不同之处在于Batch Normalization和Dropout.Dropout比较简单,在train时会丢弃一部分连接,在eval时则不会.Batch Normalization,在train时不仅使用了当前batch的均值和方差,也使用了历史batch统计上的均值和方差,并做一个加权平均(momentum参数).在test时,由于此时batchsize不一定一致,因此不再使用当前batch的均

  • ASP.NET Core中MVC模式实现路由一

    目录 1.前言 2.设置路由中间件 3.传统路由 4.多个路由 4.1定义多个路由 4.2区分操作 5.属性路由 5.1 属性路由 5.2 使用 Http[Verb] 属性的属性路由 5.3合并路由 5.4指定属性路由的可选参数.默认值和约束 5.4自定义属性路由 相关文章 ASP.NET Core中MVC模式实现路由一 ASP.NET Core中MVC模式实现路由二 1.前言 ASP.NET Core MVC使用路由中间件来匹配传入请求的URL并将它们映射到操作(Action方法).路由在启动

  • 详解Angular开发中的登陆与身份验证

    前言 由于 Angular 是单页应用,会在一开始,就把大部分的资源加载到浏览器中,所以就更需要注意验证的时机,并保证只有通过了验证的用户才能看到对应的界面. 本篇文章中的身份验证,指的是如何确定用户是否已经登陆,并确保在每次与服务器的通信中,都能够满足服务器的验证需求.注意,并不包括对具体是否具有某一个权限的判断. 对于登陆,主要是接受用户的用户名密码输入,提交到服务器进行验证,处理验证响应,在浏览器端构建身份验证数据. 实现身份验证的两种方式 目前,实现身份验证的方法,主要有两个大类: Co

  • 在js中实现邮箱格式的验证方法(推荐)

    如下所示: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>在此处插入标题</title> <script typ

  • 浅谈iOS应用中的相关正则及验证

    1.手机号码的验证正则 正则表达式: ^((13[0-9])|(15[^4,\\D])|(18[0,0-9]))\\d{8}$ 详细解释 解释: •^...$: ^:开始 $:结束 中间为要处理的字串 •(13[0-9]): 以13开头接下来一位为0-9之间的数 13 : 以13开头 [0-9]:分割语法,13后面是0-9之间的数 •| : 或(or), 将前后两个匹配条件进行or运算 • (15[^4\\D]) : 以15开头接下来一位是除4之外的0-9数字 15 : 以15开头 [^4\\D

  • 在Django中进行用户注册和邮箱验证的方法

    本文主要介绍我在利用Django写文章时,采用的注册方法.首先说一下整体逻辑思路: •处理用户注册数据, •产生token,生成验证URL, •发送验证邮件, •用户登录网址,进行验证, •验证处理. 具体步骤: 1.添加用户 在Django中自带的User表中,有一个is_active字段,默认值是True,即用户填完表单提交之后,就可以进行登录.我们这里首先将is_acitve字段设为False,也就是说,必须经过后续的邮箱验证,才能够正常登录. 部分代码: if request.metho

  • 工作中比较实用的JavaScript验证和数据处理的干货(经典)

    在开发web项目的时候,难免遇到各种对网页数据的处理,比如对用户在表单中输入的电话号码.邮箱.金额.身份证号.密码长度和复杂程度等等的验证,以及对后台返回数据的格式化比如金额,返回的值为null,还有对指定日期之前或之后某一天或某一月的计算. 遇到需要对数据及表单验证的,我相信大家都像我一样,喜欢在网上找相关的方法,因为自己写的话,是比较耗时的.今天就给大家分享一下,自己在工作中总结的一些常用 的js. 关键代码如下所示: /** * 验证密码复杂度(必须包含数字字母) * @param str

随机推荐