SpringSecurity(四)——自定义数据源(Filter)
前言
本篇笔记记录用户自定义拦截器(Filter),这里仅举一个自定义登录拦截器的栗子。
自定义登录Filter
自定义登录Filter需要继承UsernamePasswordAuthenticationFilter
类,该类是SpringSecurity
原生解决用户信息认证的类,其中执行认证的方法为:attemptAuthentication
,自定义的登录Filter需要重写这个方法。下面的代码为完成前后端分离的登录认证Filter。
/**
* 自定义前后端分离认证filter
*/
public class LoginFilter extends UsernamePasswordAuthenticationFilter {
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
// 1. 判断是否是post 方式请求
if (!request.getMethod().equals("POST")){
throw new AuthenticationServiceException("Authentication method not supported:" + request.getMethod());
}
// 2. 判断是否是json格式请求
if (request.getContentType().equalsIgnoreCase(MediaType.APPLICATION_JSON_VALUE) || request.getContentType().equalsIgnoreCase(MediaType.APPLICATION_JSON_UTF8_VALUE)){
// 3. 从json格式中获取用户输入的用户名和密码
Map<String,String> userInfo = null;
try {
userInfo = new ObjectMapper().readValue(request.getInputStream(), Map.class);
} catch (IOException e) {
e.printStackTrace();
}
String username = userInfo.get(getUsernameParameter());
String password = userInfo.get(getPasswordParameter());
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username,password);
setDetails(request,token);
return this.getAuthenticationManager().authenticate(token);
}
return super.attemptAuthentication(request, response);
}
}
自定义Filter在业务逻辑上有一部分可以直接复写原生代码。下面说一下基本流程:
- 首先需要先判断认证请求是否为
Post
请求,如果不是则可以直接抛出异常(最好抛出认证异常,这样可以方便我们在前端接收异常信息进行后续处理); - 其次,由于前后端分离是通过
json
格式的字符串来传递数据,所以还需要对请求的数据格式进行判断; - 如果请求数据符合规则,则自定义一个
Map<Stirng,String>
格式的Map来进行接收,在接收的数据中提取用户信息的时候我们需要使用原生的用户名和密码的属性来进行获取(之前的文章中有过说明自定义用户信息的字段); - 最后其实也是原生认证的写法,将用户数据封装后提交给内部的认证器进行认证。
这个时候我们需要解决自定义数据源的问题,这个拦截器只是修改了原生认证拦截器的从form
表单中获取提交的用户信息的方式。
替换原生认证Filter
SpringSecurity中为我们提供了自定义Filter的一些API,下面进行介绍:
// 将自定义的Filter放在指定Filter后
http.addFilterAfter();
// 将自定义的Filter放在指定Filter后
http.addFilterBefore();
// 将自定义的Filter替换指定的原生Filter
http.addFilterAt();
在这里我们使用的addFilterAt()
,将原生用户认证Filter替换为自定义的Filter:
http.addFilterAt(loginFilter(), UsernamePasswordAuthenticationFilter.class);
补充判定json字符编码集
在这里需要注意的是判断数据格式是否为json
格式的时候可能会加入已经不推荐使用的判断UTF-8json格式的判定,但是个人认为这个还是尽量加上,用于提升代码的健壮性。在OPEN Java官网中关于Java编码规范提供了一篇提案,在提案中提供了一些关于不同系统不同版本关于Java中原生API对于字符集编码设定的问题。
在Java中有一些类中(比如File类),有一些方法中并没有对于字符编码集有请执行的设定,它们默认为JVM
默认提供的编码集,这种情况下根据不同系统、平台以及版本等情况,可能会存在字符编码集不匹配造成的一些问题。
官方文档中给出的集中解决方案中,最佳方案为:在项目部署时提供JVM
运行参数,指定编码集。另一种是官方提供新的API(添加指定编码集的参数)来覆盖之前的方法(但是可能会造成代码冗余)。所以我在这里两种方法都使用。
如果对这个感兴趣则可以点击下方链接去官网中查看提案原文。
总结
本篇笔记中记录了自定义用户认证Filter,主要是记录一个思路。
前一段时间在B站上看到一个视频,视频中主要讲述不要死学SpringBoot和SpringCloud,看到很多人都在评论中攻击UP主。其实我觉得UP主说的也没毛病。这种思想是编程思想的本质。编程语言那么多,但是万变不离其宗,编程思想尤为重要。但是这是针对还有时间有精力甚至有经济基础的朋友,如果大家能在大一开始就明确知道编程为何物,明确知道编程的本质以及基础,那么便可以放开手脚在学习基础、技术等时间外放心大胆的学习编程思维;如果到了需要考编程技术来养活自己的时候,就真的不建议刻意的学习编程思维了,因为付出和回报不成正比,当有了几年一线开发经验,可能会在升职为管理层或者转行做教师的时候,会发现学习编程思维会让自己更进一步。
目前国内比较稀缺的不是码农,而是真正有编程思维的专业能力者,码农可以在重复做出已经被证实可以实现的产品,但是在实现一些暂时知识理论而没有实际产品基础的方向就会显得捉襟见肘。为什么多年前的程序员那么值钱,并不是因为当年的程序员多么稀缺,而是那个时候真的想在程序员的行业中站稳脚跟就需要一直努力地学习,相关的技术都要学习。而且在那个时候并没有我们现在的学习资源,只能靠自己摸索,考前辈们的经验,所以当年的程序员无一不是从零基础靠自己一点一点爬上去的。
在前辈们的努力下,互联网发展极其迅速,但是弊端也开始出现。
(以下观点只是根据市场情况来分析,并没有其他意义,各位碍国党们不要喷,我是一名中国人,我为生在中国而荣幸)。
首先是资本热钱的涌入,大家为了在互联网中赚到钱,于是会努力找到各种机会和方向来占据并瓜分市场,这个时候便出现了互联网热潮。在这个热潮中,各种公司企业如雨后春笋般出现,帮助了互联网的蓬勃发展。
但是在行业内部竞争逐渐结束,该出局的出局、该转行的转行,市场份额基本掌握在几个大方向的企业中。在这个时候,企业为了巩固自己的市场地位便开始了另一轮竞赛,这次竞赛中导致出现各种产品开始迅速出现,行业内部开始缺少具备专业素质的基本人才,而大学中各种专业又和国家政策、大体发展方向以及市场未来的发展趋势而密切相关,所以大量计算机类专业开始出现。
企业继续发展,他们需要更快的产出方式,于是开始出现了各种更加方便快捷的工具、技术,帮助企业提升产出效率,于是互联网在这些年间发展速度比最开始的行业竞争时期更快。
上文说到了专业与市场相关,这个时候市场中不在大量需要能开创出新方向、新架构的人才,他们需要的是可以完成CRUD以及快速学习的人才。这个时候在课时本就不够的大学学习过程中, 对于编程基础的传授便更加困难,所以只能以速成的方式来培养人才。
说到这里,大家不要喷不能自学吗?首先,大多数人在读大学之前并不了解编程为何物,且编程思维和我们普遍思维方式有一些本质的不同。编程语言也是一门外语,和英语、法语没什么本质区别,仅仅是用作与计算机沟通的一种方式。大家想一想学一门外语入门究竟有多难(请不要秀天赋来反驳我,以大多数普通人的角度思考一下)。
言归正传,在大家仅仅为了会使用编程技术的时候,大家的内卷就变成了谁会的技术多,这个时候企业为了筛选出学习能力强,产出比更高的员工就变成了谁会的技术更多。但是大家扪心自问,面试中对答如流的技术自己真的理解他的底层吗?可能大多数人都是背了面试宝典。
如果行业内大部分人都是仅会使用技术,而不理解技术,那么经过一段时间的技术迭代、员工迭代,究竟还有多少人可以像曾经的信息爆炸时代那样为互联网行业提供快速发展的基础呢?
没有实际工作经验的朋友可以问一问前辈们,曾经了解到的系统优化、服务器优化,在大多数中小型企业中只是无脑加机器,或者筷子支大象**(别和我杠阿里怎么样、腾讯怎么样,说一下占据市场大多数的中小型企业)**。
说这么多并不是抨击什么,仅是个人看法,觉得有意思就可以看一看,如果不喜欢看就划走,就算您评论区开喷或私信骂人我也不理。
如果您觉得我说的不对可以一笑而过,我也没什么名气,没到能影响下一代的层次。本人才疏学浅,表述如有纰漏之处,恳请指正。