在上次前后端交互,我们使用的是最基本的HTML+Servlet的组合,比较基础,今天我们来讲一讲Html+Springboot框架,前后端交互实现更为简便,大大降低了我们开发人员在代码上面所花费的时间,那今天让我们一探究竟吧。
1.添加路由守卫
在前端我们在index.js中添加了路由守卫
在网址中直接去http://localhost:8081/#/main
由于路由守卫,我们不能直接进入main页面中,自动给我们跳转到登录页面中
2.验证token
添加token一块有4步:
- 登录成功后,后端生成token
- 前端接收,并保存
- 前端拦截器向后端发送
- 后端拦截器验证token
1. 登录成功后,后端生成token
package com.ffyc.common;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@Service
public class JWTUtil {
/**
* jwt 生成 token
*
* @param id
* @param account * @return
*/
public static String token(Integer id, String account) {
String token = "";
try {
//过期时间 为 1970.1.1 0:0:0 至 过期时间 当前的毫秒值 + 有效时间
Date expireDate = new Date(new Date().getTime() + 60 * 60 * 24 * 1000);//过期时间
//秘钥及加密算法 加盐
Algorithm algorithm = Algorithm.HMAC256("ZCEQIUBFKSJBFJH2020BQWE");
//设置头部信息
Map<String, Object> header = new HashMap<>();
header.put("typ", "JWT");//生成的类型
header.put("alg", "HS256");//加密算法
//携带 id,账号信息,生成签名
token = JWT.create()
.withHeader(header)//头部
.withClaim("id", id)//用户id
.withClaim("account", account)//用户账号
.withExpiresAt(expireDate)
.sign(algorithm);
} catch (Exception e) {
e.printStackTrace();
return null;
}
return token;
}
public static boolean verify(String token) {
try {
//验签
Algorithm algorithm = Algorithm.HMAC256("ZCEQIUBFKSJBFJH2020BQWE");
JWTVerifier verifier = JWT.require(algorithm).build();
DecodedJWT jwt = verifier.verify(token);
return true;
} catch (Exception e) {//当传过来的 token 如果有问题,抛出异常
return false;
}
}
/**
* 获得 token 中 playload 部分数据,按需使用
*
* @param token
* @return
*/
public static DecodedJWT getTokenInfo(String token) {
return JWT.require(Algorithm.HMAC256("ZCEQIUBFKSJBFJH2020BQWE")).build().verify(token);
}
}
将生成Token添加到admin对象中
2.前端接收,并保存
在main.js中添加验证token字段
3. 前端拦截器向后端发送
在main.js中添加
4.后端拦截器验证token
后端token拦截器:
package com.ffyc.common;
import com.fasterxml.jackson.databind.json.JsonMapper;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
//Token 验证拦截器
public class Token implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("后端Token拦截器");
String adminToken=request.getHeader("token");
boolean res=JWTUtil.verify(adminToken);
if(!res){
CommonResult commonResult=new CommonResult(202,res,"token失效");
JsonMapper jsonMapper=new JsonMapper();
String json= jsonMapper.writeValueAsString(commonResult);
response.getWriter().print(json);
}
return res;
}
}
注册拦截器:
package com.ffyc.common;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.*;
@Configuration
public class WebConfig implements WebMvcConfigurer{
public void addInterceptors(InterceptorRegistry registry) {
InterceptorRegistration inter = registry.addInterceptor(new Token());
inter.addPathPatterns("/admin/**"); //管理员需要拦截过滤地址
inter.excludePathPatterns("/admin/loginCtl/login");//放行地址
//放行行前台首页,文章详细信息等地址
//inter.excludePathPatterns("/swagger*/**"); //放行swagger
//inter.excludePathPatterns("/v2/**");//放行swagger
//inter.excludePathPatterns("/webjars/**");//放行swagger
}
}
在网址中直接搜索127.0.0.1:8080/admin/loginCtl/test
拦截器会进行验证,没有Token,返回CommomResult
3.完成最基本的登录功能
3.1 dao层
在dao层创建接口
package com.ffyc.dao;
import com.ffyc.model.Admin;
import org.springframework.stereotype.Repository;
@Repository//使spring创建并管理对象
public interface LoginDao {
public Admin Login(Admin admin);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE
mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--接口的添加-->
<mapper namespace="com.ffyc.dao.LoginDao">
<select id="Login" resultType="Admin">
select * from admin where account=#{account} and password=#{password}
</select>
</mapper>
3.2 model层
在model层创建admin类
package com.ffyc.model;
import lombok.Data;
import lombok.Getter;
import lombok.Setter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
@Data//lombok 可以自动创建get set方法
@Getter
@Setter
public class Admin {
private Integer id;
private String account;
private int password;
private String token;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public int getPassword() {
return password;
}
public void setPassword(int password) {
this.password = password;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
}
3.2 service层
在service层写逻辑部分
package com.ffyc.service;
import com.ffyc.common.CommonResult;
import com.ffyc.common.JWTUtil;
import com.ffyc.dao.LoginDao;
import com.ffyc.model.Admin;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional
public class LoginService {
@Autowired
LoginDao loginDao;
public Admin login(Admin admin){
Admin a = loginDao.Login(admin);
return a;
}
}
3.4 web层
package com.ffyc.web;
import com.ffyc.common.CommonResult;
import com.ffyc.common.JWTUtil;
import com.ffyc.model.Admin;
import com.ffyc.service.LoginService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping(path= "/admin/loginCtl")
public class Controller {
@Autowired
LoginService loginService;
@RequestMapping(path= "/login")
//后端可以接收前端提交的json数据,但是必须是对象接收,必须要在参数前面添加@RequestBody
public CommonResult login(@RequestBody Admin admin){
Admin a = loginService.login(admin);
CommonResult commonResult=null;
if(a!=null) {
a.setToken(JWTUtil.token(a.getId(),a.getAccount()));
commonResult = new CommonResult(200, a, "登录成功");//可以对创建方法进封装
}else{
commonResult = new CommonResult(201, a, "账号密码错误");//可以对创建方法进封装
}
return commonResult;
}
}
加这个标签之后,前端就不需要再添加JsonString的方法
4.配置application.yml
#配置内置服务器的端口号
server:
port: 8080
#spring相关的配置
spring:
#配置数据库的连接信息,生成默认的数据源对象,生成JdbcTemplate,事务管理功能进行初始化
datasource:
url: jdbc:mysql://127.0.0.1:3306/map?serverTimezone=Asia/Shanghai
username: root
password: root
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource #指定数据源类型,还需要创建其对象
initialSize: 5 #初始化时建立物理连接的个数 数据库连接池相关的配置
minIdle: 1 #最小连接池数量
maxActive: 20 #最大连接池数量
#mybatis配置 创建SqlsessionFactory
mybatis:
type-aliases-package: com.ffyc.model
mapper-locations: classpath:mappers/*Mappers.xml
configuration: #mybatis settings配置
map-underscore-to-camel-case: true
cache-enabled: true