1.前言
在用户第一次登录成功后,服务端返回一个token回来,这个token是根据userId进行加密的,密钥只有服务器知道,然后浏览器每次请求都把这个token放在Header里请求,这样服务器只需进行简单的解密就知道是哪个用户了。
源码下载:https://download.csdn.net/download/m0_37499059/10627766
2.涉及的技术
1.springboot
2.跨域访问(CORS)和token校验
3.jjwt生成token
4.拦截器的使用
5.全局异常处理
6.postman工具使用
3.效果展示
4.核心代码解释
1.token生成的jar包
<!-- JJWT -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
2.跨域访问公开url
使用全局的通过注解实现的方式:
@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
//允许全部请求跨域
registry.addMapping("/**");
}
@Override
public void addInterceptors(InterceptorRegistry registry) {
//添加拦截器
registry.addInterceptor(new JwtInterceptor()).excludePathPatterns("/user/login");
}
}
3.Token工具类
package com.jimo.security;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import javax.servlet.ServletException;
import java.util.Date;
public class JwtUtil {
/**
* 私钥
*/
final static String base64EncodedSecretKey = "base64EncodedSecretKey";
/**
* 过期时间,测试使用60秒
*/
final static long TOKEN_EXP = 1000 * 60;
public static String getToken(String userName) {
return Jwts.builder()
.setSubject(userName)
.claim("roles", "user")
.setIssuedAt(new Date())
/*过期时间*/
.setExpiration(new Date(System.currentTimeMillis() + TOKEN_EXP))
.signWith(SignatureAlgorithm.HS256, base64EncodedSecretKey)
.compact();
}
/**
* @func 检查token, 只要不正确就会抛出异常
* @author jimo
* @date 17-12-12 下午6:21
*/
static void checkToken(String token) throws ServletException {
try {
final Claims claims = Jwts.parser().setSigningKey(base64EncodedSecretKey).parseClaimsJws(token).getBody();
} catch (ExpiredJwtException e1) {
throw new ServletException("token过期!");
} catch (Exception e) {
throw new ServletException("other token exception");
}
}
}
4.拦截器
package com.jimo.security;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @func 拦截token并验证,不通过则抛出异常
*/
public class JwtInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String authHeader = request.getHeader("Authorization");
if (authHeader == null) {
throw new ServletException("授权失败!");
}
try {
JwtUtil.checkToken(authHeader);
return true;
} catch (Exception e) {
throw new ServletException(e.getMessage());
}
}
}
5.Controller
package com.jimo.controller;
import com.jimo.model.User;
import com.jimo.model.common.Result;
import com.jimo.security.JwtUtil;
import org.springframework.web.bind.annotation.*;
import javax.servlet.ServletException;
@RestController
@RequestMapping("/user")
public class UserController {
@PostMapping("/login")
public Result login(@RequestBody User user) throws Exception {
if (!"admin".equals(user.getUsername())) {
throw new Exception("该用户不存在!");
}
if (!"123456".equals(user.getPassword())) {
throw new Exception("密码错误!");
}
return new Result(JwtUtil.getToken(user.getUsername()));
}
@GetMapping("/success")
public Result success() {
return new Result("login success");
}
}
6.全局异常处理
package com.jimo.exp;
import com.jimo.model.common.Result;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
/**
* @func 全局异常处理
*/
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public Result handleException(Exception e)
{
return new Result(false, e.getMessage());
}
}