记录解决SpringBoot前后端分离跨域导致的图片验证码Sessionid不一致(也即空指针异常问题)

2022-07-14 08:25:29

问题

最近在给项目开发登录注册功能,在登录的图片验证码上出现了问题,报了空指针异常。
逻辑是这样的:在登录页面,前端通过验证码接口先请求验证码,然后输入用户名密码和验证码之后,请求登录接口。在验证码接口中我用session保存验证码,在登录接口中我从session取出验证码进行校验。 postman测试没有问题,但是前端在测试时报了空指针异常。
在这里插入图片描述
于是我查看后端日志,发现请求验证码时返回给前端的sessionId和前端发送登录请求时所携带的sessionId不一致,所以后端拿到的sessionId是没有对应的验证码的,于是报了空指针异常。
在这里插入图片描述
通过查阅网上的各种信息,我们了解到这是因为跨域问题导致的,跨域我是配置过的,按照网上的办法前后端都配置了相应的跨域设置,但是依然没有解决问题。
具体可以参考链接试试,也是有人成功的:https://www.cnblogs.com/jpfss/p/9081570.html

解决办法

这个问题困扰了我们好几天,期间也是尝试过很多方法,无论是前端的跨域配置,还是后端的跨域配置都试过了,但是问题还是没有解决,不知道是不是因为我将shiro整合JWT的时候关闭了shiro的session导致的,并不清楚,我把shiro的session打开后也没有解决问题。
既然跨域这条路走不通,我们就换条路走,下面给出两种解决方法

方法一:不使用session

不使用session来实现验证码的验证,将验证码转存到redis或者数据库中,前端在通过验证码接口获取验证码时除了返回验证码本身,还要返回验证码的id,那么前端在登录的时候也要把验证码id和用户输入的验证码传给后端进行验证。这个方法并没有使用session,所以并不重点展开,我主要介绍第二种方法。

方法二:取消验证码接口,只保留登录接口来实现获取图片验证码和登录功能

使用session时对同一个页面多次刷新是不会改变sessionid的
在这里插入图片描述
既然sessionid不会改变,也就解决了我们之前的问题,那么新的问题是如何只通过一个接口实现即能返回验证码,又能实现登录功能呢。

在这里插入图片描述
我在开发登录接口时,会在登录失败时返回code为400的错误信息,在登录成功时返回code为200,也就是说只要前端发送的请求中用户名,密码,验证码任意一个为空,后端都会返回错误信息,那么只要在返回错误信息的同时将验证码的base64格式传给前端就可以了。

@PostMapping("login")publicResultlogin(@RequestBodyUser loginUser,HttpServletResponse response,HttpServletRequest request)throwsIOException{//检验loginUser元素是否完整,不完整则返回错误信息String message=newJudge().judgeUser(loginUser);if(message!="none"){//这是我封装的判断方法,如果message不为none的话,说明登录信息不完整,此时就可以返回验证码了//生成验证码String code=VerifyCodeUtils.generateVerifyCode(4);//验证码放入session
            request.getSession().setAttribute("code",code);System.out.println("getImageSession:"+request.getSession().getId());//验证码存入图片ByteArrayOutputStream bs=newByteArrayOutputStream();VerifyCodeUtils.outputImage(110,30,bs,code);//将图片转成二进制并进行Base64编码String imgsrc=Base64.byteArrayToBase64(bs.toByteArray());System.out.println(imgsrc);returnResult.fail(message,"data:image/png;base64,"+imgsrc);}//验证图片验证码String codes=(String)request.getSession().getAttribute("code");System.out.println("loginSession:"+request.getSession().getId());System.out.println("codes:"+codes);System.out.println("loginUser.getCode():"+loginUser.getCode());try{if(!codes.equalsIgnoreCase(loginUser.getCode())){//equalsIgnoreCase忽略大小写returnResult.fail("验证码错误");}}catch(NullPointerException e){
            e.printStackTrace();returnResult.fail("空指针异常");}//后面就是基本的登录逻辑了,和本问题无关,所以就不贴出来了。}

那么前端要做的事也就很简单了,在用户访问登录界面时发送一个空请求给后端,从而拿到验证码图片的base64格式,再加上img src标签后就可以展示图片了,用户填写完整的登录信息后再给后端发送请求就能实现登录了。
附上前端代码:
一、在点击用户名输入框的时候 发送一个请求获取验证码。

$('.inputName').one("focus",function(){
        $.ajax({
            url:'http://*.*.*.*/user/login',
            type:'POST',
            contentType:"application/json",
            dataType:'json',//json 返回值类型
            data:JSON.stringify({
                username:""+ rt.value,
                password:""+ uu.value,
                code:""+ op.value}),//转化为json字符串
            xhrFields:{

                withCredentials:true},success:function(datas){$('.pp').attr("src", datas.data);}})})

二、点击登录的时候 将信息提交给服务的接口

tt[3].onclick=function(){
        ru.style.display='block';
        $.ajax({
            url:'http://*.*.*.*/user/login',
            type:'POST',
            contentType:"application/json",
            dataType:'json',//json 返回值类型
            data:JSON.stringify({
                username:""+ rt.value,
                password:""+ uu.value,
                code:""+ op.value}),//转化为json字符串
            xhrFields:{

                withCredentials:true},success:function(datas){
                console.log(datas);if(datas.code=='200'){
                    ru.style.display='none';
                    ty.innerHTML= datas.msg;
                    ty.style.display='block';
                    tt[3].setAttribute("class","sub");alert('好兄弟即将起航');var seconds=3;setInterval(function(){
                        seconds--;if(seconds==0){
                            window.location.href="../main_page.html";}},1000);}else{
                    ru.style.display='none';
                    ty.innerHTML= datas.msg;
                    ty.style.display='block';}}});}

最后自然是成功解决了验证码报空指针的问题了
在这里插入图片描述

在这里插入图片描述

  • 作者:骑行去看海
  • 原文链接:https://blog.csdn.net/sgsx11/article/details/120288407
    更新时间:2022-07-14 08:25:29