1.后端认证返回token
/**
* 认证成功时发送JWT
*
* @param request
* @param response
* @param chain
* @param authResult
* @throws IOException
* @throws ServletException
*/
@Override
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain,
Authentication authResult)
throws IOException, ServletException {
User user = (User) authResult.getPrincipal();
// 签名算法
Algorithm algorithm = Algorithm.HMAC256(tokenSecret);
//生成JWT Token(令牌)
String access_token = JWT.create()
//主体
.withSubject(user.getUsername())
//令牌过期时间30 分钟
.withExpiresAt(new Date(System.currentTimeMillis() + 30 * 60 * 1000))
//令牌发行者
.withIssuer(request.getRequestURL().toString())
//权限
.withClaim("roles",
user.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()))
// .withClaim("abc", "")
//签名
.sign(algorithm);
log.info("Generate JWT Token: {}", access_token);
Map<String, String> tokens = new HashMap<>();
tokens.put("access_token", access_token);
//设置响应标头
response.setContentType("application/json; charset=UTF-8");
response.addHeader(HttpHeaders.AUTHORIZATION,"Bearer "+access_token);
response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN,"*");
response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS,"PUT,GET,POST,DELETE,OPTIONS");//"PUT,GET,POST,DELETE"
response.setHeader(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS,
"Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild");
//生成JSON 写回客户端
ObjectMapper objectMapper = new ObjectMapper();
//响应是 Body
objectMapper.writeValue(response.getOutputStream(), tokens);
}
2.前端接收Token存入sessionStorage
login(){
getData('http://localhost:8080/api/user/login', 'post', this.param)
.then((resp) => {
console.log(resp.access_token);
console.log(resp)
if(resp!==null){
sessionStorage.setItem("userToken",resp.access_token)
router.push("/")
console.log("页面跳转成功")
}else {
console.log("页面跳转失败")
}
});
}
3.在main.js中加入axios请求的拦截器将token加入请求头
import axios from "axios";
axios.interceptors.request.use(config =>{
if(sessionStorage.getItem("userToken")){
console.log(sessionStorage.getItem("userToken"))
config.headers.Authorization ="Bearer "+sessionStorage.getItem("userToken");
console.log(config.headers.Authorization);
}
return config;
},error => {
return Promise.reject(error)
})
4.自定义请求头会触发OPTIONS预检请求并且导致403跨域错误,在后端将OPTIONS放行(预检请求不会带上token,所以会导致403,只需要在后端对OPTIONS进行放行)
//写在webConfig
protected void configure(HttpSecurity http) throws Exception {
//禁止跨站请求攻击
http.csrf().disable()
// 指定cors配置
.cors().configurationSource(configurationSource());
}
// cors配置+++++++++++++++++++++++++++====
CorsConfigurationSource configurationSource(){
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.setAllowCredentials(true);
corsConfiguration.addAllowedOrigin("http://localhost:3000");
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
UrlBasedCorsConfigurationSource url = new UrlBasedCorsConfigurationSource();
url.registerCorsConfiguration("/**",corsConfiguration);
return url;
}