使用springboot整合shiro进行登录认证(md5+盐值+散列次数)

news/2024/5/17 2:38:10

准备工作:
md5加密算法:

public class md5Test {@Testpublic void md5() {//明文(123) + 盐值(monian) + 加密次数(1024)    ==>  密文  8ea680082c12d7d878a3a97214ebbdc2Md5Hash md5Hash = new Md5Hash("123","monian",1024);System.out.println(md5Hash);}
}

创建Springboot项目web、Lombok:

由于我们使用的是jsp,需要引入相关的依赖(防止访问页面时,访问的是资源路径(访问后不解析,会直接下载文件))

此外还有shiro依赖、mybatis-plus、mysql、druid:

 <!--jsp--><dependency><groupId>org.apache.tomcat.embed</groupId><artifactId>tomcat-embed-jasper</artifactId></dependency><!--shiro--><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring-boot-starter</artifactId><version>1.5.3</version></dependency>
<!--    mybatis-plus    --><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.1</version></dependency>
<!--    mysql    --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency>
<!--    druid    --><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.6</version></dependency>

properties.yml配置文件: 

server:port: 8080servlet:context-path: /shiro
spring:mvc:view:prefix: /suffix: .jspdatasource:driver-class-name: com.mysql.cj.jdbc.Drivertype: com.alibaba.druid.pool.DruidDataSourcepassword: chenusername: rooturl: jdbc:mysql://localhost:3306/shiro?useSSL=false&userUnicode=true&characterEncoding=utf8druid:max-active: 10
mybatis-plus:configuration:map-underscore-to-camel-case: truelog-impl: org.apache.ibatis.logging.stdout.StdOutImpltype-aliases-package: net.wanho.entitymapper-locations: classpath:mapper/*.xml

创建Realm(数据源)对象:

/*** 自定义Realm ,继承AuthorizingRealm*/
public class ShiroRealm extends AuthorizingRealm {@Resourceprivate UserService userService;/*** 认证* Authentication 证明真实性,鉴定;身份验证*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {//先怼死 不要从数据库找数据 admin 123UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) authenticationToken;//用户输入用户名String username = usernamePasswordToken.getUsername();QueryWrapper<User> wrapper = new QueryWrapper<>();wrapper.eq("username",username);User user = userService.getOne(wrapper);//账号不存在if(ObjectUtils.isEmpty(user)){throw new UnknownAccountException("账号不存在!!!");}//        String password = (String) usernamePasswordToken.getCredentials();
//        if (!password.equals("8ea680082c12d7d878a3a97214ebbdc2")){
//            throw new IncorrectCredentialsException("账号密码错误!!!");
//        }//密文密码//存放盐值ByteSource byteSource = ByteSource.Util.bytes(user.getSalt());return new SimpleAuthenticationInfo(username,user.getPassword(),byteSource,super.getName());}/*** 授权* Authorization 批准书,授权书;批准*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {return null;}
}

添加shiro的配置:

@Configuration
public class ShiroConfig {/***  获得认证的数据源*  realm 领域、范围*  @return*/@Beanpublic Realm getRealm() {ShiroRealm realm = new ShiroRealm();//使用 md5 加密//创建密码匹配器,支持散列算法HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();credentialsMatcher.setHashAlgorithmName("MD5"); //设置加密算法credentialsMatcher.setHashIterations(1024); //设置散列次数//设置密码匹配器realm.setCredentialsMatcher(credentialsMatcher);return realm;}/*** 创建安全管理器 类似于: 自定义XXService* 自定义的Realm交给SecurityManager管理* @param realm* @return*/@Beanpublic DefaultWebSecurityManager getDefaultWebSecurityManager(Realm realm) {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();securityManager.setRealm(realm);return securityManager;}/*** ShiroFilter ,对资源进行过滤处理* 将SecurityManager交给ShiroFilterFactoryBean管理* @param securityManager* @return*/@Beanpublic ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {ShiroFilterFactoryBean filterFactoryBean = new ShiroFilterFactoryBean();//设置过滤路径 anon 默认 authc 认证 roles perms 授权 logout 退出Map<String,String> map = new LinkedHashMap<>();map.put("/index.jsp","authc");map.put("/login.jsp","anon");//设置安全管理器filterFactoryBean.setSecurityManager(securityManager);filterFactoryBean.setFilterChainDefinitionMap(map);filterFactoryBean.setLoginUrl("/login.jsp");return filterFactoryBean;}
}

配置mybatis-plus的配置:

/*** 配置类: 类似于 spring => *.xml*/
@Configuration
@MapperScan("net.wanho.mapper")
public class MybatisPlusConfig {/*** 配置拦截器* @return*/@Beanpublic MybatisPlusInterceptor configMybatisPlusInterceptor(){//创建拦截器实例MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();//添加 分页拦截器 指定数据库interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}
}

添加实体:

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("t_user")
public class User implements Serializable {private Integer id;private String username;private String password;private String salt;
}

mapper:

public interface UserMapper extends BaseMapper<User> {User selectUsernameAndPassword(String username);
}

service:

public interface UserService extends IService<User> {
}
@Service
@Transactional(rollbackFor = Exception.class)
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}

controller:

@Controller
@RequestMapping("/user")
public class UserController {@PostMapping("/login")public String login(String username, String password, Model model){try {//获得用户主体Subject subject = SecurityUtils.getSubject();//封装 tokenUsernamePasswordToken token = new UsernamePasswordToken(username, password);//调用登录subject.login(token);//subject.checkPermission("user:view");//跳转到主页return "index";} catch (Exception e) {//设置错误消息model.addAttribute("msg","账号或密码错误!!!") ;//跳到到登录页面return "login";}}@GetMapping("/logout")public String logout(){Subject subject = SecurityUtils.getSubject();subject.logout();return "redirect:/login.jsp";}
}

注意注解!!!,不能使用@RestController,返回的是json/xml文件,不会进行解析;

前端界面:

index.jsp:

<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags" %>
<%@page contentType="text/html;UTF-8" pageEncoding="UTF-8" isErrorPage="false" %>
<!doctype html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title>
</head>
<body>
<%--受限资源--%>
<h1>系统主页</h1>
<h2>欢迎: <shiro:principal/> </h2>
<a href="${pageContext.request.contextPath}/user/logout">安全退出</a>
<h1>系统主页</h1><ul><li><a href="#">用户管理</a></li><li><a href="#">商品管理</a></li><li><a href="#">订单管理</a></li><li><a href="#">物流管理</a></li>
</ul>
</body>
</html>

 login.jsp:

<%@page contentType="text/html;UTF-8" pageEncoding="UTF-8" isErrorPage="false" isELIgnored="false" %>
<!doctype html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport"content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title>
</head>
<style>.massage{color: red;}
</style>
<body>
<h1>登录界面</h1>
<a href="${pageContext.request.contextPath}/user/logout">安全退出</a>
<form action="${pageContext.request.contextPath}/user/login" method="post">用户名:<input type="text" name="username" > <br/>密码:<input type="password" name="password"> <br><input type="submit" value="登录">
</form>
<hr>
<h4 class="massage">${msg}</h4>
</body>
</html>

浏览器测试: 

  

当点击安全退出按钮,默认返回的是login.jsp界面,再次输入index.jsp,也会跳到登陆界面 

知识点梳理:
Spring MVC中内嵌9大成员,使用model可以将数据带到前端界面

 


http://www.mrgr.cn/p/28111203

相关文章

ResNet50算法

ResNet (Residual net)是残差网络的通用概念,而 ResNet50 是一个具体的网络结构,其由50个卷积层组成。ResNet50 是指包含了50个卷积层(包括卷积层、池化层、全连接层等)的 ResNet 网络。ResNet50 是基于 ImageNet 数据集上的训练所提出的一个具体网络结构。 ResNet 核心:…

ResNet网络学习

ResNet (Residual net)是残差网络的通用概念,而 ResNet50 是一个具体的网络结构,其由50个卷积层组成。ResNet50 是指包含了50个卷积层(包括卷积层、池化层、全连接层等)的 ResNet 网络。ResNet50 是基于 ImageNet 数据集上的训练所提出的一个具体网络结构。 ResNet 核心:…

vue3中使用scss

安装依赖npm install sass sass-loader --save-dev局部使用 <style scoped lang="scss"> ...定义样式 </style>全局共享样式变量,在assets/style 文件夹中定义 mixin.scss文件,并设置一些样式;在其他文件使用定义的变量前需要引入样式文件表 在vite.c…

Python 数学应用(四)

原文:zh.annas-archive.org/md5/123a7612a4e578f6816d36f968cfec22 译者:飞龙 协议:CC BY-NC-SA 4.0第十一章:其他主题 在本章中,我们将讨论一些在本书前几章中没有涉及的主题。这些主题大多涉及不同的计算方式以及优化代码执行的其他方式。其他主题涉及处理特定类型的数据…

【数学建模】2024认证杯C题完整思路和代码论文解析

经过不懈的努力&#xff0c;2024认证杯数学建模C题的完整论文和代码已完成&#xff0c;代码为A题全部4问的代码&#xff0c;论文包括摘要、问题重述、问题分析、模型假设、符号说明、模型的建立和求解&#xff08;问题1模型的建立与求解、问题2模型的建立与求解、问题3模型的建…

[已解决]问题:root.users.hdfs is not a leaf queue

问题&#xff1a;root.users.hdfs is not a leaf queue CDH集群报错&#xff1a; Exception in thread “main” org.apache.hadoop.yarn.exceptions.YarnException: Failed to submit application_1713149630679_0005 to YARN : root.users.hdfs is not a leaf queue 思路 …

lua 环境安装

下载地址&#xff1a; https://luabinaries.sourceforge.net/download.html 安装环境变量 检查一下是否安装成功&#xff0c;有版本号&#xff0c;打印一句话&#xff0c;如下表示成功 idea 安装插件&#xff0c;方便编写lua脚本 配置一下idea 运行测试 local function m…

毕业设计4.10

测试echarts前后端,实现数据库中温度信息的图表化显示

物联网实战--驱动篇之(五)TEA和AES加密算法

目录 一、前言 二、TEA算法 三、AES算法 四、加解密测试 五、安全性保障 一、前言 物联网的安全性是经常被提及的一个点&#xff0c;如果你的设备之间通讯没有加密的话&#xff0c;那么攻击者很容易就能获取并解析出报文的协议&#xff0c;从而根据攻击者的需要进行设备操…

Linux文件IO

文章目录 1.文件操作的知识点2.文件的理解3.标记位4.文件的本质5.文件的应用5.1 重定向5.1.1 重定向的接口5.1.2 缓冲区的理解 6.文件描述符2(stderr)的深入理解7.磁盘文件7.1 物理磁盘7.2 磁盘的存储结构7.3 磁盘存储的逻辑7.4 细化磁盘存储 8.dd指令挂载 1.文件操作的知识点 …

拿到鹅厂的Offer啦!

企鹅想必是大部分开发者梦寐以求的归宿了,除了有丰富的福利之外,还有优厚的薪资待遇,以及大厂光环,即使干几年跳槽了,也能有很多选择。 这不,训练营的小伙伴在拿下字节跳动之后,又拿下一城,顺便把腾讯也给收了:但弱水三千只取一瓢饮,去哪家公司变成了最大的苦恼了,果…

参考文献

参考文献 Cite This For Me: Harvard, APA, MLA Reference Generator 参考文献排版 \begin{thebibliography}{99} \bibitem{1} Lustenhouwer N, Maynard D S, Bradford M A, et al. A trait-based understanding of wood decomposition by fungi[J]. Proceedings of the Nation…

利用AbortController,取消正在发送的请求

参考文章&#xff1a;https://blog.csdn.net/qq_45560350/article/details/130588101 解决问题&#xff1a;再图层中点击仓库的时候&#xff0c;点击后又取消掉&#xff0c;我们希望这个请求可以被取消掉&#xff0c;我们口可以利用AbortController控制器对象 实操&#xff1a…

禁止chrome自动更新

1、打开注册表,可以修改win+R,然后输入regedit 2、打开HKEY_LOCAL_MACHINE总文件夹下的SOFTWARE子文件夹找到Policies文件3、在该文件夹下进行新增文件,文件夹为新增项,先进行新增Google然后再到该文件夹下新增Update文件夹 4、然后再新增DWORD(32位)值(D),名称修改为Updat…

Elasticsearch初步了解学习记录

目录 前言 一、ElasticSearch是什么&#xff1f; 二、使用步骤&#xff08;python版&#xff09; 1.引入包 2.连接数据库 3.创建索引 4.写入数据 5.查询数据 三、相关工具介绍 1.ES浏览器插件 总结 前言 随着数据量的不断增加&#xff0c;传统的查询检索在速度上遇…

AskManyAI:一个GPT、Claude、Gemini、Kimi等顶级AI的决斗场

一直以来很多人问我能不能有个稳定&#xff0c;不折腾的全球AI大模型测试网站&#xff0c;既能够保证真实靠谱&#xff0c;又能够保证稳定、快速&#xff0c;不要老动不动就挂了、出错或者漫长的响应。 直到笔者遇到了AskManyAI&#xff0c;直接就惊艳住了&#xff01; 话不多…

vscode 代码格式化设置

1.设置默认格式化工具 ctrl+shift+P,筛选“Format Document”,设置Prettier为默认、 2.设置保存自动格式化打开 VSCode,并打开你想要格式化的代码文件。 在菜单栏中,选择“文件”>“首选项”>“设置”(快捷键 Ctrl+,)。 在搜索框中输入“format on save”,然后点…

分享2024 golang学习路线

写在前面 Go语言&#xff08;也称为Golang&#xff09;是Google开发的一种静态强类型、编译型语言&#xff0c;它具有简洁、快速、安全、并发等特点&#xff0c;尤其适合构建大型软件、微服务架构和云平台服务。Go的学习曲线相对平缓&#xff0c;社区活跃&#xff0c;是现代编…

2-81. 创建交易窗口 UI 并实现拖拽交易打开交易窗口

关闭窗口 修改 EventHandler修改 InventoryUI修改 NPCFunction打开窗口人物无法移动 修改 Enums修改 EventHandler修改 NPCFunction修改 Player打开对话框人物还可以移动 修改 DialogController打开商店的时候同时打开背包 调整背包和商店锚点位置修改 InventoryUI拖拽物品实现…