Spring cloud微服务安全实战-3-5 API安全机制之认证(2)
基于Http协议的认证方式有很多。本节我们只讲一个最简单的HttpBasic认证。聪明就可以看出来,这是一个最基础的认证,好处是简单方便,所有的主流浏览器都支持,问题就是并不是非常安全的,但是帮我们大家理解认证这个概念是足够的。
首先要对认证信息做Base64的加密,加密之前要把这两个信息组合起来。用户名冒号密码组合成这样一个字符串。然后拿这个字符串做Base64的字符串的加密。并生成一个字符串。
把生成的串放到http请求的 请求头里面。带个前缀 Basic +空格 + 加密后的字符串。
开始写代码
先加上字符串处理的工具的引用。commons-lang3这里面有个字符串处理的工具类
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
建一个新的过滤器BaseicAuthecationFilter
继承OncePerRequestFilter
@Component声明称一个组件,这样SpringBoot会自动把他加到应用的过滤器链上。
注入UserRepository
用java.util这个包下的也可以,用Base64Utils这个也可以。
根据冒号拆分成两个字符串
创建这个根据UserName查询的方法
之前写的findByName删掉。
User findByUsername(String username);
StringUtils用的都是apache.commons.lang3这个包下的类。

package com.imooc.security.filter; import com.imooc.security.user.User; import com.imooc.security.user.UserRepository; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.Base64Utils; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; @Component public class BasicAuthecationFilter extends OncePerRequestFilter { @Autowired private UserRepository userRepository; protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String authHeader = request.getHeader("Authorization"); if(StringUtils.isNotBlank(authHeader)){ String token64 = StringUtils.substringAfter(authHeader, "Basic "); String token = new String(Base64Utils.decodeFromString(token64));//解码 //根据冒号拆分成两个字符串 String[] items = StringUtils.splitByWholeSeparatorPreserveAllTokens(token, ":"); String username = items[0]; String password = items[1]; User user = userRepository.findByUsername(username); if(user!=null && StringUtils.equals(password,user.getPassword())){ request.setAttribute("user",user); } } filterChain.doFilter(request,response); } }
因为我们还没有写审计等的代码,这里我们先在controller里面写代码,先看到效果。
user里面getId获取到id和当前的接口传递过来的参数id对象,如果不相等就抛出异常。
遇到的错误
出现问题的原因
修改成Long即可
继续
在User实体类里面。写一个方法,buildInfo,。把User对象转换成UserInfo对象。
public UserInfo buildInfo(){
UserInfo info=new UserInfo();
BeanUtils.copyProperties(this,info);
return info;
}
JPA提供的findById默认的返回类型是一个Optional的类型。
UserServiceImpl 。所以要先get()再调用buildInfo()
public UserInfo get(Long id) { return userRepository.findById(id).get().buildInfo(); }
运行测试
现在在请求头里面根本没有带认证信息。这里是个get请求。查询id为1的用户信息
{ "timestamp": "2019-12-10T09:05:46.377+0000", "status": 500, "error": "Internal Server Error", "message": "身份认证信息异常,获取用户信息失败", "path": "/users/1" }
在过滤器里面,相当于这一段完全没有执行
经过过滤器会进入到controller里面。在Arttribute里面拿到的是空。所以就抛出了异常。
@GetMapping("/{id}") public UserInfo get(@PathVariable Long id, HttpServletRequest request){ User user=(User) request.getAttribute("user"); if(user == null || !user.getId().equals(id)) { throw new RuntimeException("身份认证信息异常,获取用户信息失败"); } return userService.get(id); }
发出去的完整的信息里面已经带了请求头的信息了。但是 依然报了异常
这是因为创建的用户的id是5 但是回去的用户信息id是1。所以造成了id的不匹配。
把请求的id改成5
这样用户信息成功返回
以上就是认证起作用的一个简单的例子。
postman里面的设置
结束
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架