- 如果不保存session的话,在每次通过http访问服务器,服务器都会新开一个线程,线程中不保存前一次访问留下的session记录。
- 而对于获取验证码等操作,这些都需要上一次访问服务器记录的session,如不保存session的话那么在服务器端对应的验证码则为空。
-
2022-10-23 18:03:09.377 DEBUG 640 --- [nio-8080-exec-3] com.tian.sms.util.CodeCheck : das
2022-10-23 18:03:09.377 DEBUG 640 --- [nio-8080-exec-3] com.tian.sms.util.CodeCheck : null
- 服务器采用SpringBoot服务器,验证码生成采用Google的kaptcha框架。
package com.tian.sms.controller;
import com.google.code.kaptcha.Constants;
import com.google.code.kaptcha.Producer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.imageio.ImageIO;
import javax.naming.ldap.PagedResultsControl;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.IOException;
//获取验证码接口
@Controller
public class KaptchaController {
private static final Logger log = LoggerFactory.getLogger(KaptchaController.class);
public static String CHECK_CODE;
@Autowired
private Producer kaptchaProducer;
@RequestMapping("/kaptcha")
public void getKaptchaImage(HttpServletRequest request, HttpServletResponse response) throws IOException {
HttpSession session = request.getSession();
response.setDateHeader("Expires", 0);
response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
response.addHeader("Cache-Control", "post-check=0, pre-check=0");
response.setHeader("Pragma", "no-cache");
response.setContentType("image/jpeg");
//生成验证码
String capText = kaptchaProducer.createText();
log.debug(capText);
CHECK_CODE = capText;
session.setAttribute(Constants.KAPTCHA_SESSION_KEY, capText);
log.debug(session.getAttribute(Constants.KAPTCHA_SESSION_KEY).toString());
log.debug("kaptcha"+request.getParameter("date"));
//向客户端写出
BufferedImage bi = kaptchaProducer.createImage(capText);
ServletOutputStream out = response.getOutputStream();
ImageIO.write(bi, "jpg", out);
try {
out.flush();
} finally {
out.close();
}
}
public String getCheckCode(){
return CHECK_CODE;
}
}
- 由上可看出,验证码的数据是保存在服务器的session中的,所以Android端不能是同Glide框架来直接获取图片,暂时未知Glide框架如何保存session,所以采用Okhttp框架来发送请求获取session,并将session保存。
package com.tian.mygraduatesign.activity;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Parcel;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.bumptech.glide.Glide;
import com.tian.mygraduatesign.R;
import com.tian.mygraduatesign.pojo.School;
import com.tian.mygraduatesign.pojo.User;
import com.tian.mygraduatesign.util.GetJson;
import com.tian.mygraduatesign.util.UrlUtil;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import kotlin.reflect.KVariance;
import okhttp3.Call;
import okhttp3.FormBody;
import okhttp3.Headers;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okio.BufferedSink;
public class LoginActivity extends Activity {
ImageView codeCheck;
LoginActivity loginActivity;
Date date;
Spinner spinnerSchool;
TextView accountText;
TextView passwordText;
TextView codeText;
OkHttpClient okHttpClient;
List<String> schoolName;
List<String> schoolEName;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login_layout);
codeCheck = findViewById(R.id.login_check_img);
loginActivity = this;
date = new Date();
spinnerSchool = findViewById(R.id.login_spinner);
accountText = findViewById(R.id.login_account);
passwordText = findViewById(R.id.login_password);
codeText = findViewById(R.id.login_check_code);
okHttpClient = new OkHttpClient();
imgChange.start();
Glide.with(this).load(UrlUtil.url + "/kaptcha?date=" + date.getTime()).into(codeCheck);
codeCheck.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//刷新验证码图片 验证码具有网络缓存 需要添加时间戳参数
date = new Date();
imgChange.start();
}
});
}
Thread imgChange = new Thread(new Runnable() {
@Override
public void run() {
Request request = new Request.Builder().addHeader("cookie", GetJson.session).url(UrlUtil.url + "/kaptcha?date=" + date.getTime()).get().build();
Call call = okHttpClient.newCall(request);
try {
Response response = call.execute();
//修改session
Headers headers = response.headers();
List<String> cookies = headers.values("Set-Cookie");
String s = cookies.get(0);
GetJson.session = s.substring(0,s.indexOf(";"));
//发送图片byte数组给handler处理
byte[] bytes = response.body().bytes();
Message imgMsg = new Message();
Bundle bundle = new Bundle();
bundle.putByteArray("values",bytes);
imgMsg.setData(bundle);
codeImgHandler.sendMessage(imgMsg);
} catch (IOException e) {
e.printStackTrace();
}
}
});
//处理验证码图片UI更改
Handler codeImgHandler = new Handler(){
@Override
public void handleMessage(@NonNull Message msg) {
Bundle data = msg.getData();
byte[] values = data.getByteArray("values");
Bitmap bitmap = BitmapFactory.decodeByteArray(values,0,values.length);
codeCheck.setImageBitmap(bitmap);
}
};
public void loginUser(View view) {
new Thread(new Runnable() {
@Override
public void run() {
Message loginMsg = new Message();
Bundle bundle = new Bundle();
//获取spinner控件的选择的学校简写
int i = schoolName.indexOf(((TextView)spinnerSchool.getSelectedView()).getText().toString());
FormBody formBody = new FormBody.Builder().add("school",schoolEName.get(i)).add("account",accountText.getText().toString())
.add("password",passwordText.getText().toString())
.add("code",codeText.getText().toString()).build();
//发送表单请求
Request build = new Request.Builder().addHeader("cookie",GetJson.session).url(UrlUtil.url + "/login").post(formBody).build();
Call call = okHttpClient.newCall(build);
try {
Response execute = call.execute();
//修改session
Headers headers = execute.headers();
List<String> cookies = headers.values("Set-Cookie");
String s = cookies.get(0);
GetJson.session = s.substring(0,s.indexOf(";"));
//获取json字符串
String body = execute.body().string();
bundle.putString("values",body);
loginMsg.setData(bundle);
loginHandle.sendMessage(loginMsg);
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}
- 这样就能将session通过cookie进行保存。