news 2026/6/19 15:16:09

security第十四集 多因素认证-认证服务

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
security第十四集 多因素认证-认证服务
  1. 多因素认证是一种实现安全访问控制的常见方法,基本的设计理念在于,用户如果想要访问最终的资源,至少需要通过两种认证机制
  2. 一种常见的做法是分成两个步骤实现,第一步通过用户名和密码获取一个认证码(Authentication Code),第二步基于用户名和该认证码进行安全访问
  3. 下面我们基于这种思想,搭建一个多因素认证系统。可以借助上两集的用户体系上进行修改
  4. 数据库中新建一个表auth_code , 其对应的实体类如下所示
packagecom.kai.oauth.securityservice.entity;importlombok.Data;@DatapublicclassAuthCode{privateStringid;privateStringusername;privateStringcode;}
  1. 新建AuthController,并暴露两个端点 /user/auth 和 /authcode/check
packagecom.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;//基于用户名和密码的认证,返回authcode@PostMapping("/user/auth")publicMap<String,String>userAuth(@RequestBodyUseruser){Stringauthcode=userService.userAuth(user);Map<String,String>map=newHashMap<>();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);}}}
  1. 上诉代码中的 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查询用户信息Useru=userMapper.selectByUserName(user.getUsername());if(u!=null){//验证密码是否匹配if(passwordEncoder.matches(user.getPassword(),u.getPassword())){//密码匹配后生成authcode,并返回StringauthCode=generateOrRenewAuthCode(u);returnauthCode;}else{thrownewBadCredentialsException("Bad credentials");}}else{thrownewBadCredentialsException("Bad credentials");}}//基于用户名与authcode的认证实现publicbooleancodeAuth(AuthCodeauthCode){//通过username查询auth_code表数据AuthCodecode=authCodeMapper.findAuthCodeByUsername(authCode.getUsername());if(code!=null){//判断code与auth_code表的code是否一致if(authCode.getCode().equals(code.getCode())){returntrue;}}returnfalse;}//生成authcode方法privateStringgenerateOrRenewAuthCode(Useruser){//随机生成一个uuid当做authcodeStringgeneratedCode=UUID.randomUUID().toString().replaceAll("-","");//根据username查询auth_code表数据AuthCodeauthCode=authCodeMapper.findAuthCodeByUsername(user.getUsername());//没有数据就新增一条,有则更新if(authCode!=null){authCode.setCode(generatedCode);authCodeMapper.updateAuthCode(authCode);}else{AuthCodecode=newAuthCode();code.setId(UUID.randomUUID().toString().replaceAll("-",""));code.setUsername(user.getUsername());code.setCode(generatedCode);authCodeMapper.insertAuthCode(code);}returngeneratedCode;}}
  1. 关于AuthCode的查询代码如下所示
packagecom.kai.oauth.securityservice.mapper;importcom.kai.oauth.securityservice.entity.AuthCode;importorg.apache.ibatis.annotations.Mapper;@MapperpublicinterfaceAuthCodeMapper{AuthCodefindAuthCodeByUsername(Stringusername);voidinsertAuthCode(AuthCodeauthCode);voidupdateAuthCode(AuthCodeauthCode);}
  1. AuthCodeMapper.xml 如下所示
<?xml version="1.0"encoding="UTF-8"?><!DOCTYPEmapperPUBLIC"-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.kai.oauth.securityservice.mapper.AuthCodeMapper"><resultMap id="authCodeResultMap"type="com.kai.oauth.securityservice.entity.AuthCode"><id property="id"column="id"/><result property="username"column="username"/><result property="code"column="code"/></resultMap><select id="findAuthCodeByUsername"resultMap="authCodeResultMap">select*from auth_code where username=#{username}</select><insert id="insertAuthCode"parameterType="com.kai.oauth.securityservice.entity.AuthCode">insert into auth_codevalues(#{id},#{username},#{code})</insert><update id="updateAuthCode"parameterType="com.kai.oauth.securityservice.entity.AuthCode">UPDATEauth_codeSETcode=#{code}WHEREusername=#{username}</update></mapper>
  1. 修改MyWebSecurityConfigAdapter,把/user/auth 和 /authcode/check 端点设置成无需认证
protectedvoidconfigure(HttpSecurityhttp)throwsException{http.csrf().disable().httpBasic();//任何请求都无需认证http.authorizeRequests().anyRequest().permitAll();}
  1. 现在用postman来测试一下这两个端点,先来试试访问/user/auth端点,生成authcode
  2. 利用生成的authcode值 ,来访问/authcode/check端点,可以看到返回的status状态码是200,而非403,说明走的是 response.setStatus(HttpServletResponse.SC_OK);

    多因素认证的服务已经搭建完毕,下一集 我们 新创建一个项目来请求此认证服务
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/19 14:53:53

【Springboot毕设全套源码+文档】基于Spring Boot的骑行路线规划与分享平台设计与实现(丰富项目+远程调试+讲解+定制)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围&#xff1a;&am…

作者头像 李华
网站建设 2026/6/19 14:51:34

架构革命:New API重新定义企业级AI服务治理范式

架构革命&#xff1a;New API重新定义企业级AI服务治理范式 【免费下载链接】new-api 基于One API的二次开发版本&#xff0c;仅供个人管理渠道使用&#xff0c;请勿用于商业API分发&#xff01; 项目地址: https://gitcode.com/gh_mirrors/newa/new-api 在AI服务日益复…

作者头像 李华
网站建设 2026/6/19 14:42:08

LLM.swift多平台适配策略:从macOS到visionOS的兼容性指南

LLM.swift多平台适配策略&#xff1a;从macOS到visionOS的兼容性指南 【免费下载链接】LLM.swift LLM.swift is a simple and readable library that allows you to interact with large language models locally with ease for macOS, iOS, watchOS, tvOS, and visionOS. 项…

作者头像 李华
网站建设 2026/6/19 14:40:48

企业级ChatTTS私有化部署:离线环境与国密SM4音频加密传输实战

1. 项目概述&#xff1a;为什么我们需要一个“离线加密”的ChatTTS WebUI&#xff1f;最近在语音合成圈子里&#xff0c;ChatTTS的热度一直居高不下&#xff0c;尤其是它那接近真人、富有表现力的音色&#xff0c;让很多开发者都想把它集成到自己的项目里。但问题也随之而来&am…

作者头像 李华
网站建设 2026/6/19 14:39:33

Python嵌套类实战:从语法到设计模式的优雅封装

1. Python嵌套类基础&#xff1a;语法与核心特性 第一次看到Python嵌套类时&#xff0c;我盯着屏幕愣了三秒——类里面还能再套一个类&#xff1f;这就像俄罗斯套娃般的代码结构让我既好奇又困惑。经过多年实战&#xff0c;我发现嵌套类其实是Python面向对象编程中一颗被严重低…

作者头像 李华