security第十四集 多因素认证-认证服务
多因素认证是一种实现安全访问控制的常见方法基本的设计理念在于用户如果想要访问最终的资源至少需要通过两种认证机制一种常见的做法是分成两个步骤实现第一步通过用户名和密码获取一个认证码Authentication Code第二步基于用户名和该认证码进行安全访问下面我们基于这种思想搭建一个多因素认证系统。可以借助上两集的用户体系上进行修改数据库中新建一个表auth_code , 其对应的实体类如下所示packagecom.kai.oauth.securityservice.entity;importlombok.Data;DatapublicclassAuthCode{privateStringid;privateStringusername;privateStringcode;}新建AuthController并暴露两个端点 /user/auth 和 /authcode/checkpackagecom.kai.oauth.securityservice.controller;importcom.kai.oauth.securityservice.entity.AuthCode;importcom.kai.oauth.securityservice.entity.User;importcom.kai.oauth.securityservice.service.UserService;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.web.bind.annotation.PostMapping;importorg.springframework.web.bind.annotation.RequestBody;importorg.springframework.web.bind.annotation.RestController;importjavax.servlet.http.HttpServletResponse;importjava.util.HashMap;importjava.util.Map;RestControllerpublicclassAuthController{AutowiredprivateUserServiceuserService;//基于用户名和密码的认证返回authcodePostMapping(/user/auth)publicMapString,StringuserAuth(RequestBodyUseruser){StringauthcodeuserService.userAuth(user);MapString,StringmapnewHashMap();map.put(authcode,authcode);returnmap;}//基于用户名和authcode的认证PostMapping(/authcode/check)publicvoidcodeAuth(RequestBodyAuthCodeauthCode,HttpServletResponseresponse){if(userService.codeAuth(authCode)){response.setStatus(HttpServletResponse.SC_OK);}else{response.setStatus(HttpServletResponse.SC_FORBIDDEN);}}}上诉代码中的 userService.userAuth(user) 与 userService.codeAuth(authCode) 方法具体实现如下所示packagecom.kai.oauth.securityservice.service;importcom.kai.oauth.securityservice.entity.AuthCode;importcom.kai.oauth.securityservice.entity.User;importcom.kai.oauth.securityservice.mapper.AuthCodeMapper;importcom.kai.oauth.securityservice.mapper.UserMapper;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.security.authentication.BadCredentialsException;importorg.springframework.security.crypto.password.PasswordEncoder;importorg.springframework.stereotype.Service;importjava.util.UUID;ServicepublicclassUserService{AutowiredprivateUserMapperuserMapper;AutowiredprivateAuthCodeMapperauthCodeMapper;AutowiredprivatePasswordEncoderpasswordEncoder;//基于用户名与密码的认证实现publicStringuserAuth(Useruser){//根据username查询用户信息UseruuserMapper.selectByUserName(user.getUsername());if(u!null){//验证密码是否匹配if(passwordEncoder.matches(user.getPassword(),u.getPassword())){//密码匹配后生成authcode并返回StringauthCodegenerateOrRenewAuthCode(u);returnauthCode;}else{thrownewBadCredentialsException(Bad credentials);}}else{thrownewBadCredentialsException(Bad credentials);}}//基于用户名与authcode的认证实现publicbooleancodeAuth(AuthCodeauthCode){//通过username查询auth_code表数据AuthCodecodeauthCodeMapper.findAuthCodeByUsername(authCode.getUsername());if(code!null){//判断code与auth_code表的code是否一致if(authCode.getCode().equals(code.getCode())){returntrue;}}returnfalse;}//生成authcode方法privateStringgenerateOrRenewAuthCode(Useruser){//随机生成一个uuid当做authcodeStringgeneratedCodeUUID.randomUUID().toString().replaceAll(-,);//根据username查询auth_code表数据AuthCodeauthCodeauthCodeMapper.findAuthCodeByUsername(user.getUsername());//没有数据就新增一条有则更新if(authCode!null){authCode.setCode(generatedCode);authCodeMapper.updateAuthCode(authCode);}else{AuthCodecodenewAuthCode();code.setId(UUID.randomUUID().toString().replaceAll(-,));code.setUsername(user.getUsername());code.setCode(generatedCode);authCodeMapper.insertAuthCode(code);}returngeneratedCode;}}关于AuthCode的查询代码如下所示packagecom.kai.oauth.securityservice.mapper;importcom.kai.oauth.securityservice.entity.AuthCode;importorg.apache.ibatis.annotations.Mapper;MapperpublicinterfaceAuthCodeMapper{AuthCodefindAuthCodeByUsername(Stringusername);voidinsertAuthCode(AuthCodeauthCode);voidupdateAuthCode(AuthCodeauthCode);}AuthCodeMapper.xml 如下所示?xml version1.0encodingUTF-8?!DOCTYPEmapperPUBLIC-//mybatis.org//DTD Mapper 3.0//ENhttp://mybatis.org/dtd/mybatis-3-mapper.dtdmapper namespacecom.kai.oauth.securityservice.mapper.AuthCodeMapperresultMap idauthCodeResultMaptypecom.kai.oauth.securityservice.entity.AuthCodeid propertyidcolumnid/result propertyusernamecolumnusername/result propertycodecolumncode//resultMapselect idfindAuthCodeByUsernameresultMapauthCodeResultMapselect*from auth_code where username#{username}/selectinsert idinsertAuthCodeparameterTypecom.kai.oauth.securityservice.entity.AuthCodeinsert into auth_codevalues(#{id},#{username},#{code})/insertupdate idupdateAuthCodeparameterTypecom.kai.oauth.securityservice.entity.AuthCodeUPDATEauth_codeSETcode#{code}WHEREusername#{username}/update/mapper修改MyWebSecurityConfigAdapter把/user/auth 和 /authcode/check 端点设置成无需认证protectedvoidconfigure(HttpSecurityhttp)throwsException{http.csrf().disable().httpBasic();//任何请求都无需认证http.authorizeRequests().anyRequest().permitAll();}现在用postman来测试一下这两个端点先来试试访问/user/auth端点生成authcode利用生成的authcode值 来访问/authcode/check端点可以看到返回的status状态码是200而非403说明走的是 response.setStatus(HttpServletResponse.SC_OK);多因素认证的服务已经搭建完毕下一集 我们 新创建一个项目来请求此认证服务

相关新闻

3D打印机固件革命:如何用Klipper实现超高速高质量打印?

3D打印机固件革命:如何用Klipper实现超高速高质量打印?

3D打印机固件革命:如何用Klipper实现超高速高质量打印? 【免费下载链接】klipper Klipper is a 3d-printer firmware 项目地址: https://gitcode.com/GitHub_Trending/kl/klipper Klipper是一款革命性的3D打印机固件,它通过创新的主机…

2026/6/19 15:11:25阅读更多 →
终极家庭物品管理系统:HomeBox让您的物品管理变得简单高效

终极家庭物品管理系统:HomeBox让您的物品管理变得简单高效

终极家庭物品管理系统:HomeBox让您的物品管理变得简单高效 【免费下载链接】homebox A continuation of HomeBox the inventory and organization system built for the Home User 项目地址: https://gitcode.com/gh_mirrors/home/homebox 还在为找不到家里的…

2026/6/19 15:11:25阅读更多 →
MC68HC908AS32A CPU架构解析:ALU、指令集与中断机制实战

MC68HC908AS32A CPU架构解析:ALU、指令集与中断机制实战

1. MC68HC908AS32A CPU架构概览:从8位微控制器的核心说起如果你和我一样,是从8051或者PIC这类经典8位单片机入门的,那么第一次接触摩托罗拉(后来的飞思卡尔,现属NXP)的68HC08系列时,可能会觉得它…

2026/6/19 15:11:25阅读更多 →
DVWA文件包含漏洞实战:9种渗透方法与防御策略详解

DVWA文件包含漏洞实战:9种渗透方法与防御策略详解

1. 项目概述:从“文件包含”到实战渗透的思维跃迁在网络安全的学习路径上,DVWA(Damn Vulnerable Web Application)是一个绕不开的经典靶场。它像一个精心设计的“漏洞博物馆”,将Web安全中常见的漏洞,如SQL…

2026/6/19 16:41:31阅读更多 →
【实战指南】SonarQube 9.9社区版Docker部署与多语言扫描配置

【实战指南】SonarQube 9.9社区版Docker部署与多语言扫描配置

1. 从零部署SonarQube 9.9社区版 代码质量分析是开发过程中不可或缺的环节,而SonarQube作为业内知名的开源代码质量管理平台,能够帮助团队持续监控代码健康状况。使用Docker部署SonarQube社区版,可以快速搭建一套企业级的代码扫描环境。下面我…

2026/6/19 16:41:31阅读更多 →
联邦学习实战:从隐私威胁模型到安全架构演进

联邦学习实战:从隐私威胁模型到安全架构演进

1. 联邦学习中的隐私威胁全景图 第一次接触联邦学习的工程师常会问:"数据不离开本地,隐私就绝对安全了吧?"这个认知误区我在2018年做医疗联合建模时也犯过。直到某次安全审计中,我们仅通过梯度更新就反推出了患者的用药…

2026/6/19 16:41:31阅读更多 →
工业级多模态图文检索实战:从语义对齐到千万级向量索引

工业级多模态图文检索实战:从语义对齐到千万级向量索引

1. 这不是“图文搜索”演示,而是工业级多模态检索系统的实战切片 你可能在手机相册里点过“搜猫”就跳出所有带猫的照片,在电商App里上传一张裙子截图,立刻返回相似款式的文字详情页——这些看似轻巧的功能背后,是一整套融合视觉理…

2026/6/19 16:41:31阅读更多 →
机器学习项目开工前必须做好的五件事:从可复用到可扩展的工程化实践

机器学习项目开工前必须做好的五件事:从可复用到可扩展的工程化实践

1. 项目概述:为什么“搭架子”比写代码更关键我带过二十多个从零起步的机器学习落地项目,最常听到的一句话是:“老师,模型调好了,但上线后总出问题。”后来我发现,90%的问题根源不在算法本身,而…

2026/6/19 16:41:31阅读更多 →
2026世界杯钓鱼攻击深度解析:从自动化攻击链到纵深防御实战

2026世界杯钓鱼攻击深度解析:从自动化攻击链到纵深防御实战

1. 项目概述:一场围绕顶级赛事的数字攻防战 最近在追踪网络威胁情报时,一个现象级的攻击事件进入了我的视野:围绕2026年美加墨世界杯,一场大规模的钓鱼攻击正在悄然爆发。安全研究团队已经监测到超过222个精心构造的欺诈域名&…

2026/6/19 16:36:30阅读更多 →
Photobucket付费墙背后:5美元买童年回忆却落得一场空!

Photobucket付费墙背后:5美元买童年回忆却落得一场空!

1. 付费墙初现如今身处万亿市值公司林立的时代,我们也不能轻易放弃5美元。就像Photobucket,它曾相当于过去的Imgur,我们小时候常把图片上传到这个网站,然后在各种论坛上分享链接,它简单好用,尽职尽责。但最…

2026/6/19 0:04:37阅读更多 →
如何在5分钟内掌握Mermaid Live Editor:实时图表编辑终极指南

如何在5分钟内掌握Mermaid Live Editor:实时图表编辑终极指南

如何在5分钟内掌握Mermaid Live Editor:实时图表编辑终极指南 【免费下载链接】mermaid-live-editor Edit, preview and share mermaid charts/diagrams. New implementation of the live editor. 项目地址: https://gitcode.com/GitHub_Trending/me/mermaid-live…

2026/6/19 0:04:37阅读更多 →
yuzu模拟器内存修改技术深度解析:金手指功能实现原理与实践指南

yuzu模拟器内存修改技术深度解析:金手指功能实现原理与实践指南

yuzu模拟器内存修改技术深度解析:金手指功能实现原理与实践指南 【免费下载链接】yuzu 项目地址: https://gitcode.com/GitHub_Trending/yuz/yuzu yuzu作为目前最流行的开源Nintendo Switch模拟器,不仅提供了完整的游戏运行环境,还内…

2026/6/19 0:04:37阅读更多 →