系列文章目录
功能开发
登录功能分析
输入用户账户和密码,验证码,然后进行登录校验,通过登录校验后,跳转至首页功能。
与此同时,该系统所有用户都必须登录后才能跳转到后台首页,所以,登录功能在全局系统控制器的代码中实现。
验证码功能实现
验证码的前端请求
请求的是后端方法getVerifiCodeImage,该方法中,先获取请求和响应的参数,获取从工具类中创建的图片,获取图片上的验证码文本,将验证码图片响应给浏览器。
@ApiOperation("获取验证码方法")
@GetMapping("/getVerifiCodeImage")
public void getVerifiCodeImage(
@ApiParam("请求") HttpServletRequest request,
@ApiParam("响应") HttpServletResponse response){
//获取图片
BufferedImage verifiCodeImage= CreateVerifiCodeImage.getVerifiCodeImage();
//获取图片上的验证码
String verifiCode=new String(CreateVerifiCodeImage.getVerifiCode());
//将验证码文本放入session 域,为下一次验证做准备
HttpSession session=request.getSession();
session.setAttribute("verifiCode",verifiCode);
/*
* 将验证码图片响应到浏览器 response输出流
* 将生成的验证码图片,按照PNG格式传给浏览器。
* */
try {
ServletOutputStream outputStream= response.getOutputStream();
ImageIO.write(verifiCodeImage,"PNG",outputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
登录校验功能
登录校验功能首先需要判断,用户输入的验证码和系统图片的验证码文本是否一致,如若不一致,则会提示验证码有误,请刷新后重试。如若判断一致后,会先将现有session中移除现有验证码,在进行用户类型验证(管理员,学生,老师)。
在这里,采用map类型,进行用户响应数据的存放,将传入的用户类型分为三种,1代表管理员,2代表学生,3 代表老师。(以管理员用户为例)将传入的对象,在数据库进行查询,如果查询找到了,则为admin对象。如果没有找到,则admin对象为null,那么说明用户名或者密码错误。
/*
* 登录校验
* */
@ApiOperation("登录的方法")
@PostMapping("/login")
//传入两个参数,一个是系统的验证码图片,一个是用户输入的验证码
public Result login(@ApiParam("登录提交的表单")@RequestBody LoginForm loginForm,HttpServletRequest request){
//验证码
HttpSession session=request.getSession();
String sessionVerifiCode=(String) session.getAttribute("verifiCode");
String loginVerifiCode=loginForm.getVerifiCode();
//验证码判断,是否失效或者为空
if ("".equals(sessionVerifiCode ) || null==sessionVerifiCode){
return Result.fail().message("验证码失效,请刷新后重试");
}
//判断用户输入验证码和系统验证码是否相同,不区分大小写
if (!sessionVerifiCode.equalsIgnoreCase(loginVerifiCode)){
return Result.fail().message("验证码有误,请输入后重试");
}
//从session移除现有验证码
session.removeAttribute("verifiCode");
//分用户类型验证 管理员,学生,老师等
//准备一个map用户存放响应的数据
Map<String,Object> map=new LinkedHashMap<>();
switch (loginForm.getUserType()){
//管理员表
case 1:
try {
//传入的对象,判断登录,数据库中查询,找到为admin,如果为null,即没有找到。
Admin admin= adminService.login(loginForm);
if (null !=admin){
//用户的id 和类型,转换为一个密文,以token形式的名称反馈前端
String token= JwtHelper.createToken(admin.getId().longValue(),1);
map.put("token",token);
}else {
throw new RuntimeException("用户名或者密码有误");
}
return Result.ok(map);
}catch (RuntimeException e){
e.printStackTrace();
//异常对象抛出来的信息 new RuntimeException("用户名或者密码有误");
return Result.fail().message(e.getMessage());
}
//学生信息
case 2:
try {
Student student= studentService.login(loginForm);
if (null !=student){
String token=JwtHelper.createToken(student.getId().longValue(),2);
map.put("token",token);
}else {
throw new RuntimeException("用户名或者密码错误");
}
return Result.ok(map);
}catch (RuntimeException e){
e.printStackTrace();
return Result.fail().message(e.getMessage());
}
case 3:
try {
Teacher teacher= teacherService.login(loginForm);
if (null !=teacher){
String token=JwtHelper.createToken(teacher.getId().longValue(),3);
map.put("token",token);
}else {
throw new RuntimeException("用户名或者密码错误");
}
return Result.ok(map);
}catch (RuntimeException e){
e.printStackTrace();
return Result.fail().message(e.getMessage());
}
}
return Result.fail().message("查无此人");
}
登录后跳转功能
在登录过程中,先请求login,再次请求getinfo ,来判断登录页面。
请求login页面:
响应码:200
信息:成功
data对象:用户id+类型+token有效时间 =>生成密文
第二次请求(在login请求成功后,会请求访问getinfo页面):
第二次请求中也带有一个token。
请求信息头:
响应admin 的数据信息:
源码
@Api(tags = "系统控制器")
@RestController
@RequestMapping("/sms/system")
public class SystemController {
@Autowired
private AdminService adService;
@Autowired
private StudentService studentService;
@Autowired
private TeacherService teacherService;
/*
* token 判断登录
* */
@ApiOperation("通过taken口令来获取当前登录的用户信息的方法")
@GetMapping("/getInfo")
public Result getInfoByToken(
//请求头 token
@ApiParam("token口令") @RequestHeader("token") String token){
boolean expiration=JwtHelper.isExpiration(token);//验证token是否过期。
if (expiration){
//token无效
return Result.build(null, ResultCodeEnum.TOKEN_ERROR);
}
//从token解析出 用户id+用户类型
Long userId=JwtHelper.getUserId(token);
Integer userType=JwtHelper.getUserType(token);
//判断登录状态
Map<String,Object> map=new LinkedHashMap<>();
//用户类型
switch (userType){
case 1:
//根据adminid查询一个对象,键值对
Admin admin=adminService.getAdminById(userId);
map.put("userType",1);
map.put("user",admin);
break;
case 2:
Student student=studentService.getStudentById(userId);
map.put("userType",2);
map.put("user",student);
break;
case 3:
Teacher teacher=teacherService.getByTeacherById(userId);
map.put("userType",3);
map.put("user",teacher);
break;
}
return Result.ok(map);
}
}
这段代码同时可以优化为以下代码,(后续不少代码给出的是优化后或有一定变动后的代码)