JWT-springboot
demo地址
搭建springboot + mybatis + jwt环境
- 引入依赖
<!-- 引入mybatis-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.3.1</version>
</dependency>
<!-- 引入lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
<!-- 引入druid-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.9</version>
</dependency>
<!-- mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.15</version>
</dependency>
- 编写配置
#配置数据库
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/jwt?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&useSSL=false
spring.datasource.username=root
spring.datasource.password=123
#配置mybatis
mybatis.mapper-locations=classpath:com/kk/mapper/*.xml #指定mapper配置文件位置
mybatis.type-aliases-package=com.wkk.entity #指定起别名所在包
#配置日志使用
logging.level.root=info
logging.level.com.wkk=debug #指定包日志
- 开发数据库
DROP TABLE IF EXISTS user
CREATE TABLE user(
id int(11) NOT NULL AUTO_INCREMENT COMMENT'主键',
name varchar(80) DEFAULT NULL COMMENT '用户名',
password varchar(40) DEFAULT NULL COMMENT '用户密码',
PRIMARY KEY(id)
)ENGINE=InnODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
- 开发entity
@Data
@Accessors(chain = true)
public class User {
private Integer id;
private String name;
private String password;
}
- 开发DAO接口和mapper.xml
@Mapper
public interface UserDAO {
//直接根据用户名密码登录
User login(User user);
}
<mapper namespace="com.wkk.dao.UserDAO">
<select id="login" parameterType="com.wkk.entity.User" resultType="com.wkk.entity.User">
select *
from user
where name = #{name}
and password = #{password}
</select>
</mapper>
- 开发Service 接口以及实现类
public interface UserService {
User login(User user); //登录接口
}
@Service
@Transactional
public class UserServiceImpl implements UserService {
@Autowired
private UserDAO userDAO;
@Override
@Transactional(propagation = Propagation.SUPPORTS)
public User login(User user) {
User userDB = userDAO.login(user);
if (userDB != null) {
return userDB;
}
throw new RuntimeException("登录失败~");
}
}
问题
- 使用上述方式每次都要传递token数据, 每个方法都需要验证token代码冗余, 不够灵活? 如何优化
- 使用拦截器进行优化
使用拦截器优化
public class JWTInterceptor implements HandlerInterceptor {
//jwt最好放在请求头里面,不要放在请求参数中
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
Map<String, Object> map = new HashMap<>();
//获取请求头中令牌
String token = request.getHeader("token");
try {
//验证令牌
JWTUtils.verify(token);
// map.put("state", true);
// map.put("msg", "请求成功");
return true; //放行请求
} catch (SignatureVerificationException e) { //签名不一致异常
e.printStackTrace();
map.put("msg", "无效签名");
} catch (TokenExpiredException e) { //令牌过期异常
e.printStackTrace();
map.put("msg", "令牌过期异常");
} catch (AlgorithmMismatchException e) { //算法不匹配异常
e.printStackTrace();
map.put("msg", "算法不匹配异常");
} catch (Exception e) {
e.printStackTrace();
map.put("msg", "token无效!!");
}
map.put("state", false); //设置状态
//将map转为json jackson
String json = new ObjectMapper().writeValueAsString(map);
response.setContentType("application/json;charset=UTF-8");
response.getWriter().println(json); //把对应的json发给前端
return false;
}
}
拦截器中要获取请求头中的token
获取token
请求头带上token访问接口
引用
编程不良人