java token跨域_springmvc跨域+token验证

本文详细介绍了如何在 Spring MVC 中处理 App 后台的跨域设置,包括通过 @CrossOrigin 注解和配置类两种方式。同时,文章讲解了如何在拦截器中设置 HTTP 报文头中的 Token 以及 Token 的生成实现。通过示例代码展示了拦截器 HeaderTokenInterceptor 和 JWT 工具类 JwtUtil 的用法,用于验证和更新 Token。
摘要由CSDN通过智能技术生成

1)app后台跨域设置

2)拦截器中设置http报文header中token

3)token的生成实现

====================================================================================================

1,app后台跨域的设置

1.1   springmvc4 有直接在请求映射中对跨域的处理,只需加一个@CrossOrign()

@CrossOrigin(origins = "http://localhost:9000")

@GetMapping("/greeting")

public Greeting greeting(@RequestParam(required=false, defaultValue="World") String name) {

System.out.println("==== in greeting ====");

return newGreeting(counter.incrementAndGet(), String.format(template, name));

}

对全局请求路径的拦截的,则需要在配置类里声明:

@Bean

publicWebMvcConfigurer corsConfigurer() {

return newWebMvcConfigurerAdapter() {

@Override

public voidaddCorsMappings(CorsRegistry registry) {

registry.addMapping("/greeting-javaconfig").allowedOrigins("http://localhost:9000");

}

};

}

“/greeting-javaconfig” 则是你定义的请求路径了,你也可以直接设置为/api/*之类的,allowedOrigins也可以匹配成*

可以参考官方文档:https://spring.io/guides/gs/rest-service-cors/

1.2 通过filter过滤器进行处理

其实,spring的拦截器也是可以处理跨域的问题,但对于post+json的支持不是很好,用拦截器的支持会好一些:

首先,定义拦截器:

public class CrossFilter extendsOncePerRequestFilter {

@Override

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throwsServletException, IOException {

if (request.getHeader("Access-Control-Request-Method") != null && "OPTIONS".equals(request.getMethod())) {

//CORS "pre-flight" request

response.addHeader("Access-Control-Allow-Origin", "*");

response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");

response.addHeader("Access-Control-Allow-Headers", "Content-Type");

response.addHeader("Access-Control-Max-Age", "1800");//30 min

}

filterChain.doFilter(request, response);

}

}

其次,在web.xml设置过滤:

cors

cn.***.filter.CrossFilter

cors

/*

当然spring4  appalication.xml 也可以配置成:

3)我的配置类配置:

importorg.slf4j.Logger;

importorg.slf4j.LoggerFactory;

importorg.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.annotation.*;

importorg.springframework.core.env.Environment;

importorg.springframework.web.cors.CorsConfiguration;

importorg.springframework.web.cors.UrlBasedCorsConfigurationSource;

importorg.springframework.web.filter.CorsFilter;

importorg.springframework.web.servlet.HandlerInterceptor;

importorg.springframework.web.servlet.ViewResolver;

import org.springframework.web.servlet.config.annotation.*;

importorg.springframework.web.servlet.mvc.Controller;

importorg.springframework.web.servlet.view.InternalResourceViewResolver;

importjava.util.ArrayList;

importjava.util.List;

/*** Created by ThinkPad on 2017/6/15.

*/@Configuration

@EnableWebMvc

@ComponentScan(basePackages = {"com.ouyang.teson"},useDefaultFilters = true)

@PropertySource({"classpath:teson.properties"})

public class WebConfig extendsWebMvcConfigurerAdapter{

private final static Logger logger = LoggerFactory.getLogger(WebConfig.class);

publicViewResolver viewResolver() {

InternalResourceViewResolver viewResolver = newInternalResourceViewResolver();

viewResolver.setPrefix("/WEB-INF/views/jsp/function/");

viewResolver.setSuffix(".jsp");

returnviewResolver;

}

//静态文件

@Override

public voidaddResourceHandlers(ResourceHandlerRegistry registry) {

logger.info("addResourceHandlers");

registry.addResourceHandler("/static/**").addResourceLocations("/WEB-INF/static/");

}

//允许跨域的接口

@Override

public voidaddCorsMappings(CorsRegistry registry) {

registry.addMapping("/api/*").allowedOrigins("*")

.allowCredentials(false)

.allowedMethods("GET", "POST", "DELETE", "PUT")

.allowedHeaders("Access-Control-Allow-Origin","Access-Control-Allow-Headers","Access-Control-Allow-Methods","Access-Control-Max-Age")

.exposedHeaders("Access-Control-Allow-Origin")

.maxAge(3600);

}

}

2) 在拦截器中设置token

在拦截器中设置token这个比较简单,我就直接带过了,看配置:

拦截器类:HeaderTokenInterceptor.java

packagecom.ouyang.teson.intercept;

importcom.ouyang.teson.WebConfig;

importcom.ouyang.teson.util.JwtUtil;

importorg.slf4j.Logger;

importorg.slf4j.LoggerFactory;

importorg.springframework.beans.factory.annotation.Autowired;

importorg.springframework.web.servlet.HandlerInterceptor;

importorg.springframework.web.servlet.ModelAndView;

importjavax.servlet.http.HttpServletRequest;

importjavax.servlet.http.HttpServletResponse;

importjava.io.IOException;

importjava.io.PrintWriter;

/*** Created by ThinkPad on 2017/6/20.

*/

public class HeaderTokenInterceptor implementsHandlerInterceptor {

private final static Logger logger = LoggerFactory.getLogger(HeaderTokenInterceptor.class);

@Autowired

JwtUtil jwtUtil;

@Override

public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throwsException {

//String contentPath=httpServletRequest.getContextPath();

//System.out.println("contenxPath:"+contentPath);

String requestURI=httpServletRequest.getRequestURI();

String tokenStr=httpServletRequest.getParameter("token");

String token="";

if(requestURI.contains("/api/")){

token=httpServletRequest.getHeader("token");

if(token==null && tokenStr==null){

System.out.println("real token:======================is null");

String str="{'errorCode':801,'message':'缺少token,无法验证','data':null}";

dealErrorReturn(httpServletRequest,httpServletResponse,str);

return false;

}

if(tokenStr!=null){

token=tokenStr;

}

token=jwtUtil.updateToken(token);

System.out.println("real token:=============================="+token);

System.out.println("real ohter:=============================="+httpServletRequest.getHeader("Cookie"));

}

httpServletResponse.setHeader("token",token);

/*httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");

httpServletResponse.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");

httpServletResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT");*/

return true;

}

@Override

public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throwsException {

}

@Override

public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throwsException {

}

//检测到没有token,直接返回不验证

public voiddealErrorReturn(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,Object obj){

String json =(String)obj;

PrintWriter writer = null;

httpServletResponse.setCharacterEncoding("UTF-8");

httpServletResponse.setContentType("text/html; charset=utf-8");

try{

writer =httpServletResponse.getWriter();

writer.print(json);

} catch(IOException ex) {

logger.error("response error",ex);

} finally{

if (writer != null)

writer.close();

}

}

}

httpServletResponse.setHeader("token",token)是设置返回response的header的token信息,每一次拦截的时候,会查看是否有token,如果没有就直接报错

26524b1a3a3bec30583b0f1529054d2d.png

在webconfig.java 类中添加以下两个方法:

@Override

public voidaddInterceptors(InterceptorRegistry registry) {

registry.addInterceptor(getTokenHeader())

.addPathPatterns("/api/*")

.excludePathPatterns(

"/robots.txt");

}

//token 在header的拦截器

@Bean

publicHandlerInterceptor getTokenHeader(){

return newHeaderTokenInterceptor();

}

3) token的实现

token的实现使用jwt组件生成token,如果想要自己通过md5,或者rsa加密生成token也比较简便了,只是这个token要缓存起来,每次进行验证,验证完更新token。更新token主要是更新token里包含的时间,防止token过期。如果使用token的话,可以不用存放缓存,对于登陆验证成功后,我们会生成token,这个token还能带有用户的id等基本信息,我们就可以验证他的过期时间,id等信息。

关于jwt 组件的介绍,可以去看看我的 java组件的jwt的介绍。

直接进入主题了:

maven需要导入

com.auth0

java-jwt

3.2.0

io.jsonwebtoken

jjwt

0.7.0

jjwt 主要是对jwt进一步封装,可以快速开发web的token认证。

jwt工具类:jwtUtil.java

packagecom.ouyang.teson.util;

importio.jsonwebtoken.Claims;

importio.jsonwebtoken.JwtBuilder;

importio.jsonwebtoken.Jwts;

importio.jsonwebtoken.SignatureAlgorithm;

importorg.springframework.beans.factory.annotation.Value;

importorg.springframework.stereotype.Component;

importsun.misc.BASE64Decoder;

importsun.misc.BASE64Encoder;

importjavax.crypto.spec.SecretKeySpec;

importjavax.xml.bind.DatatypeConverter;

importjava.security.Key;

importjava.util.Date;

/*** Created by ThinkPad on 2017/6/17.

*/@Component

public classJwtUtil {

public static String sercetKey="mingtianhenganghao";

public final static long keeptime=1800000;

/*@Value("${token.sercetKey}")

public static String sercetKey;

@Value("${token.keeptime:30000}")

public static long keeptime;*/

public staticString generToken(String id, String issuer, String subject){

long ttlMillis=keeptime;

SignatureAlgorithm signatureAlgorithm =SignatureAlgorithm.HS256;

long nowMillis =System.currentTimeMillis();

Date now = newDate(nowMillis);

byte[] apiKeySecretBytes =DatatypeConverter.parseBase64Binary(sercetKey);

Key signingKey = newSecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());

JwtBuilder builder =Jwts.builder().setId(id)

.setIssuedAt(now);

if(subject!=null){

builder.setSubject(subject);

}

if(issuer!=null){

builder.setIssuer(issuer);

}

builder .signWith(signatureAlgorithm, signingKey);

if (ttlMillis >= 0) {

long expMillis = nowMillis +ttlMillis;

Date exp = newDate(expMillis);

builder.setExpiration(exp);

}

returnbuilder.compact();

}

publicString updateToken(String token){

try{

Claims claims=verifyToken(token);

String id=claims.getId();

String subject=claims.getSubject();

String issuer=claims.getIssuer();

Date date =claims.getExpiration();

returngenerToken(id, issuer, subject);

}catch(Exception ex){

ex.printStackTrace();

}

return "0";

}

publicString updateTokenBase64Code(String token) {

BASE64Encoder base64Encoder=newBASE64Encoder();

BASE64Decoder decoder = newBASE64Decoder();

try{

token=new String(decoder.decodeBuffer(token),"utf-8");

Claims claims=verifyToken(token);

String id=claims.getId();

String subject=claims.getSubject();

String issuer=claims.getIssuer();

Date date =claims.getExpiration();

String newToken =generToken(id, issuer, subject);

returnbase64Encoder.encode(newToken.getBytes());

}catch(Exception ex){

ex.printStackTrace();

}

return "0";

}

public staticClaims verifyToken(String token){

Claims claims =Jwts.parser()

.setSigningKey(DatatypeConverter.parseBase64Binary(sercetKey))

.parseClaimsJws(token).getBody();

returnclaims;

}

}

关于拦截器的处理token,及更新token,上面已经给出代码,这里不再列出。来看一下简单的控制类,仅供学习,如果要运用到生产环境还得各种配置和测试。

登陆的控制方法:

@RequestMapping("/login")

publicString login(String name,String password, Model model){

if(name==null || password==null){

return "error";

}

String token = jwtUtil.generToken("xiaoming",null,null);

model.addAttribute("token", token);

return "redirect:/api/liu";

}

这里没有做验证,只是简单根据账户密码,生成token后,重定向;接下来的任务就交给拦截器了,拦截器会拦截/api/* 下的请求,然后请求参数有token的会验证token,并更新token,并把token放到header里。

f3b6ced5ddee417096a056e2f77eeba0.png

这里可以看到token字符串有两个点,最好把jwt生成的token进行base64位编码,jwtUtil.java里有updateTokenBase64Code(String token)就是处理token进行base64位编码的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值