前后台分离使用token
使用场景:前后端分离时(后台使用的是springboot,前端使用的是uniapp),当前台请求登录接口时,后台进行储存用户信息,并生成token,并返回给前端.前端请求其他接口都需要在头部带着token ,才能请求。下面来具体代码说明吧。(对你们有帮助的谢谢点赞收藏,错误的地方也谢谢评论提出,加以改善)
第一步:在pom.xml 文件中引入jar包
<!-- token包-->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
第二步:使用工具类JwtUtils.java (这是生成token,和获取token的机制,直接复制可用)
package com.example.changcai.smart_device.tool;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.tomcat.util.codec.binary.Base64;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.security.Key;
import java.util.Date;
import java.util.Map;
/**
* jwt
*/
public class JwtUtils {
/**
* @param claims 自定义的 map
* @param ttl 过期时间
* @return
*/
public static String createToken(Map<String, Object> claims, Long ttl) {
Key key = generateKey();
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
Long nowMillis = System.currentTimeMillis();
JwtBuilder builder = Jwts.builder()
.setHeaderParam("typ", "JWT")
.setHeaderParam("alg", "HS256")
.setClaims(claims)
.signWith(signatureAlgorithm, key);
if (ttl != null && ttl >= 0) {
Long expMillis = nowMillis + ttl * 1000;
Date exp = new Date(expMillis);
builder.setExpiration(exp);
}
return builder.compact();
}
/**
* @param claims 自定义的 map
* @return
*/
public static String createToken(Map<String, Object> claims) {
return createToken(claims, null);
}
/**
* @param jwt 创建的 jwt 字符串
* @return
*/
public static Claims parse(String jwt) {
if (jwt == null) {
return null;
}
try {
return Jwts.parser()
.setSigningKey(generateKey())
.parseClaimsJws(jwt)
.getBody();
} catch (Exception e) {
return null;
}
}
/**
* @return
*/
private static SecretKey generateKey() {
String stringKey = "changcai";
byte[] encodedKey = Base64.decodeBase64(stringKey);
return new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
}
/**
* @return
*/
public static Integer getParseToken(HttpServletRequest request, String token, String key) {
Claims parse = parse(token);
if (parse == null) {
return null;
}
return (Integer) parse.get(key);
}
public static Integer getParseToken(String token, String key) {
Claims parse = parse(token);
if (parse == null) {
return null;
}
return (Integer) parse.get(key);
}
/*public static String getParseTokenStr(HttpServletRequest request, String token, String key) {
Claims parse = parse(token);
if (parse == null) {
return null;
}
return (String) parse.get(key);
}*/
public static Long parseTokenStr(String token, String key) {
Claims parse = parse(token);
Object uid = parse.get(key);
return Long.parseLong(uid.toString());
}
public static void main(String[] args) {
System.out.println(generateKey());
}
}
第三步:后台登录接口存储token,并返回给前端 该controller 继承一个BaseController
@ApiOperation("用户登录接口Token")
@RequestMapping(value = "wechatLoginToken",method = RequestMethod.POST)
@ResponseBody
public ResultInfo wechatLoginToken(@RequestBody @ApiParam("用户对象") Member member1){
HashMap<String,Object> map=new HashMap();
Member member=memberService.byUserName(member1.getUsername());
if(null==member){
return new ResultInfo(203,"用户不存在!",false);
}else{
if("1".equals(member.getIsEnable())){
return new ResultInfo(204,"用户已禁用!",false);
}else if("1".equals(member.getIsDeleted())){
return new ResultInfo(204,"用户已删!",false);
}else{
if(!member.getPassword().equals(MD5Util.md5(member1.getPassword()))){
return new ResultInfo(203,"用户密码不正确!",false);
}else{
//登录成功后
HashMap<String, Object> claims = new HashMap<>();
claims.put("id", member.getId());
//token过期时间24小时
String token = JwtUtils.createToken(claims, 864000L);
map.put("token",token);
map.put("member",member);
return new ResultInfo(200,"用户登录成功!",map);
}
}
}
}
第四步:BaseController(主要解析token )
package com.example.changcai.smart_device.controller; import com.example.changcai.smart_device.entity.Member; import com.example.changcai.smart_device.service.MemberService; import com.example.changcai.smart_device.tool.JwtUtils; import com.github.pagehelper.util.StringUtil; import io.jsonwebtoken.Claims; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; import org.springframework.web.bind.annotation.ModelAttribute; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @Slf4j @Component public class BaseController { @Resource protected HttpServletRequest request; @Resource protected HttpServletResponse response; @Resource private MemberService memberService; protected Member member; @ModelAttribute public Member getMember() { String token = request.getHeader("X-Token"); if (StringUtil.isNotEmpty(token)) { System.out.println("token的值:"+token); Claims parse = JwtUtils.parse(token); Object obj = parse.get("id"); member = memberService.getById(obj.toString()); return member; } return null; } }

测试登录后返回的值
再写一个controller测试类,登录后,传token 获取member 对象
@ApiOperation("通过Token获取用户")
@RequestMapping(value = "byTokenGetMember",method = RequestMethod.POST)
@ResponseBody
public ResultInfo byTokenGetMember(){
return new ResultInfo(200,"用户登录成功!",member);
}
测试效果如

注意点1:前端请求其他接口时,都需要把token 带在头部,参数格式是:
headers:{
X-Token:前端登录成功后保存的token值
}
注意点2:如果项目使用到了swagger,请求接口heard头部想显示“X-Token”
代码截图

效果:


浙公网安备 33010602011771号