基于ruoyi中shiro框架如何实现免密登录

2023-10-29

基于ruoyi中shiro框架如何实现免密登录

所做项目与第三方合作,系统间存在一些接口调用,需要做授权登录。我们的项目整体使用springboot框架结合部分ruoyi的后台管理框架,认证登陆采用了shiro框架,密码在数据库中经过盐值(salt)+Md5加密,外部无法获知密码明文,导致无法验证通过,所以想到了免密登录的方式解决。

若依框架官网:https://gitee.com/y_project/RuoYi

经过一番摸索,也总算弄出来了,在此记录一下

1,新增一个登录类型枚举类LoginType

package com.ht.framework.shiro.token;

/**
 * 登录类型枚举类
 *
 * @author hcg
 */
public enum LoginType
{
    /**
     * 密码登录
     */
    PASSWORD("password"),
    /**
     * 免密码登录
     */
    NOPASSWD("nopasswd");

    private String desc;

    LoginType(String desc)
    {
        this.desc = desc;
    }

    public String getDesc()
    {
        return desc;
    }
}

2、自定义登录Token,继承UsernamePasswordToken类,通过构造方法区分密码登录和免密登录。

package com.ht.framework.shiro.token;

import org.apache.shiro.authc.UsernamePasswordToken;

/**
 * 自定义登录Token
 *
 * @author huang
 */
public class UserToken extends UsernamePasswordToken
{
    private static final long serialVersionUID = 1L;

    private LoginType type;

    public UserToken()
    {
    }
  //需要密码
    public UserToken(String username, String password, LoginType type, boolean rememberMe)
    {
        super(username, password, rememberMe);
        this.type = type;
    }
  //免密
    public UserToken(String username, LoginType type)
    {
        super(username, "", false, null);
        this.type = type;
    }

    public UserToken(String username, String password, LoginType type)
    {
        super(username, password, false, null);
        this.type = type;
    }

    public LoginType getType()
    {
        return type;
    }

    public void setType(LoginType type)
    {
        this.type = type;
    }
}

3、对应Realm中添加登录类型判断,例如UserRealm

/**
 * 登录认证
 */
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException
{
	UserToken upToken = (UserToken) token;
	LoginType type = upToken.getType();
	String username = upToken.getUsername();
	String password = "";
	if (upToken.getPassword() != null)
	{
		password = new String(upToken.getPassword());
	}

	User user = null;
	try
	{
		if (LoginType.PASSWORD.equals(type))
		{
		   //需要密码登录
		 	user = loginService.login(username, password);
		}
		else if (LoginType.NOPASSWD.equals(type))
		{
		  //免密登录
			user = loginService.login(username);
		}
	}
	catch (CaptchaException e)
	{
		throw new AuthenticationException(e.getMessage(), e);
	}
	catch (UserNotExistsException e)
	{
		throw new UnknownAccountException(e.getMessage(), e);
	}
	catch (UserPasswordNotMatchException e)
	{
		throw new IncorrectCredentialsException(e.getMessage(), e);
	}
	catch (UserPasswordRetryLimitExceedException e)
	{
		throw new ExcessiveAttemptsException(e.getMessage(), e);
	}
	catch (UserBlockedException e)
	{
		throw new LockedAccountException(e.getMessage(), e);
	}
	catch (RoleBlockedException e)
	{
		throw new LockedAccountException(e.getMessage(), e);
	}
	catch (Exception e)
	{
		log.info("对用户[" + username + "]进行登录验证..验证未通过{}", e.getMessage());
		throw new AuthenticationException(e.getMessage(), e);
	}
	SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());
	return info;
}

4,LoginService添加login方法,去掉密码验证。

 /**
     * 登录
     */
    public User login(String username)
    {
        // 验证码校验
        if (!StringUtils.isEmpty(ServletUtils.getRequest().getAttribute(ShiroConstants.CURRENT_CAPTCHA)))
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
            throw new CaptchaException();
        }
        // 用户名或密码为空 错误
        if (StringUtils.isEmpty(username))
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
            throw new UserNotExistsException();
        }

        // 用户名不在指定范围内 错误
        if (username.length() < UserConstants.USERNAME_MIN_LENGTH
                || username.length() > UserConstants.USERNAME_MAX_LENGTH)
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
            throw new UserPasswordNotMatchException();
        }

        // 查询用户信息
        User user = userService.selectUserByLoginName(username);

        if (user == null)
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.not.exists")));
            throw new UserNotExistsException();
        }

        if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.delete")));
            throw new UserDeleteException();
        }

        if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
        {
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.blocked", user.getRemark())));
            throw new UserBlockedException();
        }

        AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
        recordLoginInfo(user);
        return user;
    }

5、在对应的登录方法中传入LoginType.NOPASSWD调用

需要密码的登录方式

        UserToken token=new UserToken(username,password, LoginType.PASSWORD,rememberMe);
        Subject subject = SecurityUtils.getSubject();
        try
        {
            subject.login(token);
            return success();
        }
        catch (AuthenticationException e)
        {
            String msg = "用户或密码错误";
            if (StringUtils.isNotEmpty(e.getMessage()))
            {
                msg = e.getMessage();
            }
            return error(msg);
        } 

免密登录方式

        User user = userMapper.selectUserByLoginName(username);
        UserToken token=new UserToken(user.getLoginName(), LoginType.NOPASSWD);
        Subject subject = SecurityUtils.getSubject();
        subject.login(token);
        //重定向首页地址
        return "redirect:/newindex";    

到此为止,输入正确的地址就可以实现免密登录了!!

特别声明

此记录是在ruoyi的shiro框架上进行的进一步修改,只做笔记之用。

如无用你可以尝试:

如何实现用户免密登录配置方法

https://blog.csdn.net/xxfamly/article/details/92839999

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于ruoyi中shiro框架如何实现免密登录 的相关文章

  • NoInitialContextException:heroku 战争部署

    我一直在开发一个 J2EE 项目 并且在其中使用连接池 也通过部署在 heroku 上的数据库进行访问 我使用以下代码来设置 Connection 对象 Context initContext new InitialContext Cont
  • 获取文件的锁

    我想在对特定文件开始 threo read 时获取文件上的锁定 以便其他应用程序无法读取已锁定的文件并希望在线程终止时释放锁定文件 您可以获得一个FileLock https docs oracle com javase 8 docs ap
  • 使用 WebDriver 单击新打开的选项卡中的链接

    有人可以在这种情况下帮助我吗 场景是 有一个网页 我仅在新选项卡中打开所有指定的链接 现在我尝试单击新打开的选项卡中的任何一个链接 在下面尝试过 但它仅单击主 第一个选项卡中的一个链接 而不是在新选项卡中 new Actions drive
  • 当路径的点超出视野时,Android Canvas 不会绘制路径

    我在绘制路径时遇到了 Android Canvas 的一些问题 我的情况是 我有一个相对布局工作 如地图视图 不使用 google api 或类似的东西 我必须在该视图上绘制一条路径 canvas drawPath polyPath bor
  • 删除优先级队列的尾部元素

    如何删除优先级队列的尾部元素 我正在尝试使用优先级队列实现波束搜索 一旦优先级队列已满 我想删除最后一个元素 优先级最低的元素 Thanks 没有简单的方法 将元素从原始元素复制到新元素 最后一个除外 PriorityQueue remov
  • 从 MS Access 中提取 OLE 对象(Word 文档)

    我有一个 Microsoft Access 数据库 其中包含一个包含 Microsoft Word 文档的 OLE 对象字段 我试图找到代码来检索保存在 OLE 对象中的文件 以便用户可以从我的 JavaFx 应用程序中的按钮下载它 但没有
  • 在 Struts 2 中传递 URL 参数而不使用查询字符串

    我想使用类似的 URL host ActionName 123 abc 而不是像这样传递查询字符串 host ActionName parm1 123 parm2 abc 我怎样才能在 Struts 2 中做到这一点 我按照下面的方法做了
  • FileNotFoundException - Struts2 文件上传

    Strange FileNotFoundException使用Struts2上传文件时 这是 JSP 的一部分
  • Android蓝牙java.io.IOException:bt套接字已关闭,读取返回:-1

    我正在尝试编写一个代码 仅连接到运行 Android 5 0 KitKat 的设备上的 目前 唯一配对的设备 无论我尝试了多少方法 我仍然会收到此错误 这是我尝试过的最后一个代码 它似乎完成了我看到人们报告为成功的所有事情 有人能指出我做错
  • Java:从集合中获取第一项

    如果我有一个集合 例如Collection
  • 如何使用正则表达式验证 1-99 范围?

    我需要验证一些用户输入 以确保输入的数字在 1 99 范围内 含 这些必须是整数 Integer 值 允许前面加 0 但可选 有效值 1 01 10 99 09 无效值 0 007 100 10 5 010 到目前为止 我已经制定了以下正则
  • 如何删除日期对象的亚秒部分

    当 SQL 数据类型为时间戳时 java util Date 存储为 2010 09 03 15 33 22 246 如何在存储记录之前将亚秒设置为零 例如 在本例中为 246 最简单的方法是这样的 long time date getTi
  • Java、Spring:使用 Mockito 测试 DAO 的 DataAccessException

    我正在尝试增加测试覆盖率 所以我想知道 您将如何测试 DAO 中抛出的 DataAccessExceptions 例如在一个简单的 findAll 方法中 该方法仅返回数据源中的所有数据 就我而言 我使用 Spring JdbcTempla
  • 无法在 Java/Apache HttpClient 中处理带有垂直/管道栏的 url

    例如 如果我想处理这个网址 post new HttpPost http testurl com lists lprocess action LoadList 401814 1 Java Apache 不允许我这么做 因为它说竖线 是非法的
  • Karaf / Maven - 无法解决:缺少需求 osgi.wiring.package

    我无法在 Karaf 版本 3 0 1 中启动捆绑包 该包是使用 Maven 构建的并导入gson http mvnrepository com artifact com google code gson gson 2 3 1 我按照要求将
  • IntelliJ 组织导入

    IntelliJ 是否具有类似于 Eclipse 中的组织导入功能 我拥有的是一个 Java 文件 其中多个类缺少导入 例子 package com test public class Foo public Map map public J
  • Lombok @Builder 不创建不可变对象?

    在很多网站上 我看到 lombok Builder 可以用来创建不可变的对象 https www baeldung com lombok builder singular https www baeldung com lombok buil
  • 如何从 Ant 启动聚合 jetty-server JAR?

    背景 免责声明 I have veryJava 经验很少 我们之前在 Ant 构建期间使用了 Jetty 6 的包装版本来处理按需静态内容 JS CSS 图像 HTML 因此我们可以使用 PhantomJS 针对 HTTP 托管环境运行单元
  • 如何让 Emma 或 Cobertura 与 Maven 一起报告其他模块中源代码的覆盖率?

    我有一个带有 Java 代码的多模块 Maven 设置 我的单元测试在其中一个模块中测试多个模块中的代码 当然 这些模块具有相互依赖性 并且在测试执行之前根据需要编译所有相关模块中的代码 那么 如何获得整个代码库覆盖率的报告 注意 我不是问
  • 如何使用通配符模拟泛型方法的行为

    我正在使用 EasyMock 3 2 我想基于 Spring Security 为我的部分安全系统编写一个测试 我想嘲笑Authentication http docs spring io autorepo docs spring secu

随机推荐

  • three.js学习(第二天)之阻尼+自适应+js全屏

    添加阻尼效果 加载轨道控制器 import OrbitControls from three addons controls OrbitControls js 创建轨道控制器 const controls new OrbitControls
  • 常用的API接口对接方式和注意事项

    常用的API对接方式和注意事项 随着互联网的发展 API 应用程序接口 已经成为了不可或缺的一部分 API允许不同的软件系统进行通信和数据交互 为开发者提供了一种简单 灵活和高效的方式来集成不同的软件系统 在进行API对接时 有一些常用的方
  • 禅道后台命令执行漏洞 (二)

    漏洞简介 禅道是第一款国产的开源项目管理软件 它集产品管理 项目管理 质量管理 文档管理 组织管理和事务管理于一体 是一款专业的研发项目管理软件 完整地覆盖了项目管理的核心流程 禅道管理思想注重实效 功能完备丰富 操作简洁高效 界面美观大方
  • 防火墙的相关信息

    什么是防火墙 防御对象 授权用户 非授权用户 它是一种位于内部网络与外部外部网络之间的安全系统 是一种隔离 非授权用户在区域间 并过滤 对受保护网络有害流量或数据包 的设备 防火墙具有路由交换的功能 既可以做路由器也可以做交换机 防火墙的分
  • 狂神Elasticsearch笔记

    ElasticSearch笔记 我们要讲解什么 SQL like 狂神说 如果是的大数据 就十分慢 索引 ElasticSearch 搜索 百度 github 淘宝电商 1 聊一个人 2 货比三家 3 安装 4 生态圈 5 分词器ik 6
  • 如何不通过iconfont项目向已有字体图标中添加新的字体图标

    前言 今天接到一个需求 要往项目中添加一个字体图标 按照以往的惯例 就是在iconfont网站的我的项目添加需要的字体图标就行了 但这个需求是个临时需求 不想用这种方式 于是 就想直接在现有的字体图标中添加 解决方案 第一步 在iconfo
  • uGUI元素显示在角色的头顶上

    孙广东 2015 5 26 转载请注明出处 http blog csdn net u010019717 我们 游戏完全使用UGUI来工作 所以游戏中的很多元素都是UGUI的 Game Canvas画布设置为 World Space 主要也是
  • Unity3D游戏开发之设置动画(Animations)属性

    通过创建角色动画Avatar 在新的动画系统Mecanim中 Unity就设置了角色动画的骨架和蒙皮信息 从而就可以在Unity中实现角色动画了 切换到动画 Animations 选项卡 选中导入动画 Import Animation 的选
  • 人工神经网络的设计与实现(二) 感知机

    感知机 感知机 perceptron 是ANN的基本单元 至少我现在是这么觉得的 如果我学到后来发现不是 会来更正的 感知机 如下图 就是伸出几只小触手去感知这个世界 感知 感知 然后触手获取数据的加权和通过函数 f 得到的值即为该感知机的
  • 【热门框架】Mybatis-Plus标准CRUD操作

    MyBatis Plus提供了一系列标准的CRUD操作 包括insert delete update和select 下面是这些操作的指引 插入数据 1 使用实体类进行插入 User user new User user setName To
  • Idea license server地址

    以下都可以试试 http idea iteblog com key phphttp intellij mandroid cn http idea imsxm com https jetlicense nss im
  • 系统扩容心得

    author skatetime 2010 11 10 系统扩容心得 由于业务的快速发展 系统需要扩容 我们这次系统扩容动作比较小 相对不是很复杂 但过程是曲折的 结果是完美的 从开始准备到完成实施期间的每一个小细节都需要我们倍加注意 因为
  • vue-cli配置文件的查看和修改

    针对vue cli gt 3的版本 介绍两种修改方式 1 vue ui 在终端执行 vue ui 会打开页面 可以导入要管理的项目 会打开页面如下 2 在根目录下新建vue config js文件 添加要修改的配置
  • SSH整合中文

    在struts2里面配置一个常量
  • 第37章_瑞萨MCU零基础入门系列教程之DAC数模转换模块

    本教程基于韦东山百问网出的 DShanMCU RA6M5开发板 进行编写 需要的同学可以在这里获取 https item taobao com item htm id 728461040949 配套资料获取 https renesas do
  • http服务

  • ElasticSearch性能优化总结

    Elasticsearch是目前大数据领域最热门的技术栈之一 经过近8年的发展 已从0 0 X版升级至6 X版本 虽然增加了很多的特性和功能 但是在主体架构上 还是没有太多的变化 下面就把我对于ES使用实践的一些经验总结一下 供大家参考 也
  • VS2019未能返回新代码元素,可能是语法错误

    最近在写MFC的工程 在某次添加组件变量时 弹出提示框 未能返回新代码元素 可能是语法错误 检查了一遍没有语法错误 编译正常 网上所说的 将ncb文件删除就可以解决 找了半天没找到这个后缀名的文件 后来发现他们的帖子的发表时间都很老了 当初
  • 继电器驱动电路(各种单片机、CD4013触发器驱动电路图)

    继电器工作原理详解 附3种驱动电路图 继电器原理及分类 继电器知识点大全 看完一定有收获 线圈 继电器是一种电子控制器件 它具有控制系统 又称输入回路 和被控制系统 又称输出回路 通常应用于自动控制电路中 它实际上是用较小的电流去控制较大电
  • 基于ruoyi中shiro框架如何实现免密登录

    基于ruoyi中shiro框架如何实现免密登录 所做项目与第三方合作 系统间存在一些接口调用 需要做授权登录 我们的项目整体使用springboot框架结合部分ruoyi的后台管理框架 认证登陆采用了shiro框架 密码在数据库中经过盐值