今天在学习security的自定义接口的时候,想着只需要只需4步就可以自定义一个简单的登录接口,分别是
1.使用AuthenticationManager进行认证 2.对认证失败进行响应 3.获取到用户信息,然后对用户Id进行jwt加密 4.将用户信息存入Redis中,以userId为Key,loginUser为键值。
想着很简单嘛,唯一的难点可能就是认证通过之后,如何获取到之后通过UserDatailsService接口将用户信息封装成LoginUser对象后,然后再如何获取到LoginUser对象,以便得到这个信息,存到Redis中,然后进行加密,并返回给前端。
这里的可以通过认证之后返回的那个Authentication对象,调用其getPrincipal()方法,即可获取到LoginUser对象,登录的业务实现完整代码如下:
由于之前学习Redis时,是基于Linux系统下面学习的,所以在我的本机电脑上面Redis没有,我还在网上去找了资源,下载好redis,然后启动redis,然后再执行程序,正当我兴奋的打开PostMan工具想尽快进行接口测试时,意外发生了,就一直报403的错误(简单概括就是服务器不认识你,没有权限访问),接连发了几次请求都是这样,我很不理解,马上询问度娘这到底是咋回事,查了许久,大概都是说打开了CSRF保护,这个是为了防止通过伪造用户请求来访问受信用站点的非法请求访问,开了这个导致的403,他说解决方案就是,关闭CSRF :http.csrf().disable(),我看了看我的配置,如下图所示:
也没问题呀,于是乎马上尝试另外的解决方案,还有的人说是因为实体类和表字段的映射出了问题,我又仔细检查了下,这里没问题,然后又查看另外的解决方案,还有人说要创建dns缓存,再cmd命令窗口,输入ipconfig flushdns即可,这个我没尝试,因为有点离谱。
......就这样,进过一段时间的排错后,仍然没有解决问题,最后我突然想到,既然解决不了问题了,那我就debug呗,debug可以发现哪一段程序段,发生了问题,为此我还专门的学习了一下idea如何使用debug功能排错,然后我通过使用设置多个断点的方式,如下图所示:
我就断定肯定是认证出了问题,因为连第二个断点都没执行,if判断都没判断,相比就是上面
进行认证的这一关键步骤出了问题,随后我就想,既然是认证问题,那是不是会是密码检验出了问题呢?,结果还真是,因为我的数据库中密码字段存储的是明文,而我在项目中又做了
BCryptPasswordEncoder配置,一旦配置了这个,就总会将你在登录页面上输入的密码转化成加密后的字符串后,然后将这个字符串与数据库中的进行比较,因此只有当数据库中的密码字段值是暗文的时候,才能匹配成功,否则总是匹配失败,于是我立马使用一个单元测试方法
获取到这个暗文后,将其对数据库中的修改成这个,然后经过postMan测试成功了。
数据库修改:
在postMan上面测试成功:
总结:
发生这种情况原因可能有很多:
可能是没有关cfrf,也有可能是表字段和实体类属性映射出现了问题,还有可能是存在dns缓存,等等很多原因,而我的原因就在于,对数据库中密码字段值的忽略,没有修改成明文所对应的暗文。
总的来说,通过这次错误,让我见识到发生这种错误,可能是由哪些原因造成的,并且还学了debug,收获是有的。