4.6 使用 JSON 格式登录
Spring Security 中默认的登录参数传递格式是 key/value 形式,也就是表单登录格式,在实际项目中,我们可能会通过 JSON 格式来传递登录参数,这就需要我们自定义登录过滤器来实现。
通过 3.1.4 小节的介绍,大家已经明白登录参数的提取是在 UsernamePassword AuthenticationFilter 过滤器中完成的。如果我们要使用 JSON 格式登录,只需要模仿 Username PasswordAuthenticationFilter 过滤器定义自己的过滤器,再将自定义的过滤器放到 UsernamePasswordAuthenticationFilter 过滤器所在的位置即可。
思路理清了,我们来看代码实现。首先我们自定义一个 LoginFilter 继承自 Username PasswordAuthenticationFilter,代码如下:
(1)首先确保进入该过滤器中的请求是 POST 请求。
(2)根据请求的 content-type 来判断参数是 JSON 格式的还是 key/value 格式的,如果是 JSON 格式的,则直接在当前方法中处理;如果是 key/value 格式的,那直接调用父类的 attemptAuthentication 方法处理即可。
(3)如果请求参数是 JSON 格式,则首先利用 jackson 提供的 ObjectMapper 工具,将输入流转为 Map 对象,然后从 Map 对象中分别提取出用户名/密码信息并构造出 Username PasswordAuthenticationToken 对象,然后调用 AuthenticationManager 的 authenticate 方法执行认证操作。
其实 LoginFilter 中,从请求中提取出 JSON 参数之后的认证逻辑和父类 UsernamePassword AuthenticationFilter 中的认证逻辑是一致的,读者可以回顾第 3 章中关于 UsernamePassword AuthenticationFilter 的分析。
LoginFilter 定义完成后,接下来我们将其添加到 Spring Security 过滤器链中,代码如下:
(1)首先重写 configure 方法来定义一个登录用户。
(2)重写父类的 authenticationManagerBean 方法来提供一个 AuthenticationManager 实例,一会将配置给 LoginFilter。
(3)配置 loginFilter 实例,同时将 AuthenticationManager 实例设置给 loginFilter,然后再设置登录成功回调。当然,我们也可以在 loginFilter 中配置用户名/密码的参数名或者登录失败的回调。
(4)最后在 HttpSecurity 中,调用 addFilterAt 方法将 loginFilter 过滤器添加到 Username PasswordAuthenticationFilter 过滤器所在的位置。
配置完成后,重启项目,此时我们就可以使用 JSON 格式的数据来进行登录操作了,如图 4-11 所示。
图 4-11 使用 JSON 格式登录
有读者可能会注意到,当我们想要获取一个 AuthenticationManager 实例时,有两种不同的方式,第一种方式是通过重写父类的 authenticationManager 方法获取,第二种则是通过重写父类的 authenticationManagerBean 方法获取。表面上看两种方式获取到的 AuthenticationManager 实例在这里都可以运行,但实际上是有区别的。区别在于第一种获取到的是全局的 AuthenticationManager 实例,而第二种获取到的是局部的 AuthenticationManager 实例,而 LoginFilter 作为过滤器链中的一环,显然应该配置局部的 AuthenticationManager 实例,因为如果将全局的 AuthenticationManager 实例配置给 LoginFilter,则局部 Authentication Manager 实例所对应的用户就会失效,例如如下配置:
在上面这段代码中,我们将无法使用 javagirl/123 进行登录,因为 LoginFilter 中指定了全局的 AuthenticationManager 来做验证,所以局部的 AuthenticationManager 实例失效了。
在实际应用中,如果需要自己配置一个 AuthenticationManager 实例,大部分情况下,我们都是通过重写 authenticationManagerBean 方法来获取。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论