1)app后台跨域设置

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

     3)token的生成实现

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

1,app后台跨域的设置

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

  1. @CrossOrigin(origins = "http://localhost:9000")
  2. @GetMapping("/greeting")
  3. public Greeting greeting(@RequestParam(required=false, defaultValue="World") String name) {
  4. System.out.println("==== in greeting ====");
  5. return new Greeting(counter.incrementAndGet(), String.format(template, name));
  6. }

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

  1. @Bean
  2. public WebMvcConfigurer corsConfigurer() {
  3. return new WebMvcConfigurerAdapter() {
  4. @Override
  5. public void addCorsMappings(CorsRegistry registry) {
  6. registry.addMapping("/greeting-javaconfig").allowedOrigins("http://localhost:9000");
  7. }
  8. };
  9. }

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

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

1.2 通过filter过滤器进行处理

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

首先,定义拦截器:

  1. public class CrossFilter extends OncePerRequestFilter {
  2.  
  3. @Override
  4. protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
  5. if (request.getHeader("Access-Control-Request-Method") != null && "OPTIONS".equals(request.getMethod())) {
  6. // CORS "pre-flight" request
  7. response.addHeader("Access-Control-Allow-Origin", "*");
  8. response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
  9. response.addHeader("Access-Control-Allow-Headers", "Content-Type");
  10. response.addHeader("Access-Control-Max-Age", "1800");//30 min
  11. }
  12. filterChain.doFilter(request, response);
  13. }
  14. }

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

  1. <filter>
  2. <filter-name>cors</filter-name>
  3. <filter-class>cn.***.filter.CrossFilter</filter-class>
  4. </filter>
  5. <filter-mapping>
  6. <filter-name>cors</filter-name>
  7. <url-pattern>/*</url-pattern>
  8. </filter-mapping>

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

  1. <mvc:cors>
  2. <mvc:mapping path="/**" allowed-origins="*" allow-credentials="true" max-age="1800" allowed-methods="GET,POST,OPTIONS"/>
  3. </mvc:cors>

3)我的配置类配置:

  1. import org.slf4j.Logger;
  2. import org.slf4j.LoggerFactory;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.context.annotation.*;
  5. import org.springframework.core.env.Environment;
  6. import org.springframework.web.cors.CorsConfiguration;
  7. import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
  8. import org.springframework.web.filter.CorsFilter;
  9. import org.springframework.web.servlet.HandlerInterceptor;
  10. import org.springframework.web.servlet.ViewResolver;
  11. import org.springframework.web.servlet.config.annotation.*;
  12. import org.springframework.web.servlet.mvc.Controller;
  13. import org.springframework.web.servlet.view.InternalResourceViewResolver;
  14.  
  15. import java.util.ArrayList;
  16. import java.util.List;
  17.  
  18. /**
  19. * Created by ThinkPad on 2017/6/15.
  20. */
  21. @Configuration
  22. @EnableWebMvc
  23. @ComponentScan(basePackages = {"com.ouyang.teson"},useDefaultFilters = true)
  24. @PropertySource({"classpath:teson.properties"})
  25. public class WebConfig extends WebMvcConfigurerAdapter{
  26.  
  27. private final static Logger logger = LoggerFactory.getLogger(WebConfig.class);
  28. public ViewResolver viewResolver() {
  29. InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
  30. viewResolver.setPrefix("/WEB-INF/views/jsp/function/");
  31. viewResolver.setSuffix(".jsp");
  32. return viewResolver;
  33. }
  34.  
  35. //静态文件
  36. @Override
  37. public void addResourceHandlers(ResourceHandlerRegistry registry) {
  38. logger.info("addResourceHandlers");
  39. registry.addResourceHandler("/static/**").addResourceLocations("/WEB-INF/static/");
  40. }
  41.  
  42. //允许跨域的接口
  43. @Override
  44. public void addCorsMappings(CorsRegistry registry) {
  45. registry.addMapping("/api/*").allowedOrigins("*")
  46. .allowCredentials(false)
  47. .allowedMethods("GET", "POST", "DELETE", "PUT")
  48. .allowedHeaders("Access-Control-Allow-Origin","Access-Control-Allow-Headers","Access-Control-Allow-Methods"
  49. ,"Access-Control-Max-Age")
    .exposedHeaders("Access-Control-Allow-Origin")
    .maxAge(3600);
    }
  50.  
  51. }

2) 在拦截器中设置token

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

  拦截器类:HeaderTokenInterceptor.java

  1. package com.ouyang.teson.intercept;
  2.  
  3. import com.ouyang.teson.WebConfig;
  4. import com.ouyang.teson.util.JwtUtil;
  5. import org.slf4j.Logger;
  6. import org.slf4j.LoggerFactory;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.web.servlet.HandlerInterceptor;
  9. import org.springframework.web.servlet.ModelAndView;
  10.  
  11. import javax.servlet.http.HttpServletRequest;
  12. import javax.servlet.http.HttpServletResponse;
  13. import java.io.IOException;
  14. import java.io.PrintWriter;
  15.  
  16. /**
  17. * Created by ThinkPad on 2017/6/20.
  18. */
  19. public class HeaderTokenInterceptor implements HandlerInterceptor {
  20.  
  21. private final static Logger logger = LoggerFactory.getLogger(HeaderTokenInterceptor.class);
  22. @Autowired
  23. JwtUtil jwtUtil;
  24. @Override
  25. public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
  26. // String contentPath=httpServletRequest.getContextPath();
  27. // System.out.println("contenxPath:"+contentPath);
  28. String requestURI=httpServletRequest.getRequestURI();
  29. String tokenStr=httpServletRequest.getParameter("token");
  30. String token="";
  31. if(requestURI.contains("/api/")){
  32. token=httpServletRequest.getHeader("token");
  33. if(token==null && tokenStr==null){
  34. System.out.println("real token:======================is null");
  35. String str="{'errorCode':801,'message':'缺少token,无法验证','data':null}";
  36. dealErrorReturn(httpServletRequest,httpServletResponse,str);
  37. return false;
  38. }
  39. if(tokenStr!=null){
  40. token=tokenStr;
  41. }
  42. token=jwtUtil.updateToken(token);
  43. System.out.println("real token:=============================="+token);
  44. System.out.println("real ohter:=============================="+httpServletRequest.getHeader("Cookie"));
  45. }
  46.  
  47. httpServletResponse.setHeader("token",token);
  48. /* httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");
  49. httpServletResponse.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
  50. httpServletResponse.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT");*/
  51. return true;
  52. }
  53.  
  54. @Override
  55. public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {
  56. }
  57.  
  58. @Override
  59. public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {
  60. }
  61.  
  62. // 检测到没有token,直接返回不验证
  63. public void dealErrorReturn(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse,Object obj){
  64. String json = (String)obj;
  65. PrintWriter writer = null;
  66. httpServletResponse.setCharacterEncoding("UTF-8");
  67. httpServletResponse.setContentType("text/html; charset=utf-8");
  68. try {
  69. writer = httpServletResponse.getWriter();
  70. writer.print(json);
  71.  
  72. } catch (IOException ex) {
  73. logger.error("response error",ex);
  74. } finally {
  75. if (writer != null)
  76. writer.close();
  77. }
  78. }
  79. }
  1. httpServletResponse.setHeader("token",token)是设置返回responseheadertoken信息,每一次拦截的时候,会查看是否有token,如果没有就直接报错

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

  1. @Override
  2. public void addInterceptors(InterceptorRegistry registry) {
  3. registry.addInterceptor(getTokenHeader())
  4. .addPathPatterns("/api/*")
  5. .excludePathPatterns(
  6. "/robots.txt");
  7. }
  8.  
  9. //token 在header的拦截器
  10. @Bean
  11. public HandlerInterceptor getTokenHeader(){
  12. return new HeaderTokenInterceptor();
  13. }

3) token的实现

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

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

直接进入主题了:

maven需要导入

  1. <!-- java-web-token 验证授权-->
  2. <dependency>
  3. <groupId>com.auth0</groupId>
  4. <artifactId>java-jwt</artifactId>
  5. <version>3.2.0</version>
  6. </dependency>
  7. <!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
  8. <dependency>
  9. <groupId>io.jsonwebtoken</groupId>
  10. <artifactId>jjwt</artifactId>
  11. <version>0.7.0</version>
  12. </dependency>

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

jwt工具类:jwtUtil.java

  1. package com.ouyang.teson.util;
  2.  
  3. import io.jsonwebtoken.Claims;
  4. import io.jsonwebtoken.JwtBuilder;
  5. import io.jsonwebtoken.Jwts;
  6. import io.jsonwebtoken.SignatureAlgorithm;
  7. import org.springframework.beans.factory.annotation.Value;
  8. import org.springframework.stereotype.Component;
  9. import sun.misc.BASE64Decoder;
  10. import sun.misc.BASE64Encoder;
  11.  
  12. import javax.crypto.spec.SecretKeySpec;
  13. import javax.xml.bind.DatatypeConverter;
  14. import java.security.Key;
  15. import java.util.Date;
  16.  
  17. /**
  18. * Created by ThinkPad on 2017/6/17.
  19. */
  20. @Component
  21. public class JwtUtil {
  22. public static String sercetKey="mingtianhenganghao";
  23. public final static long keeptime=1800000;
  24.  
  25. /* @Value("${token.sercetKey}")
  26. public static String sercetKey;
  27. @Value("${token.keeptime:30000}")
  28. public static long keeptime;*/
  29.  
  30. public static String generToken(String id, String issuer, String subject){
  31. long ttlMillis=keeptime;
  32. SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
  33. long nowMillis = System.currentTimeMillis();
  34. Date now = new Date(nowMillis);
  35. byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(sercetKey);
  36. Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());
  37.  
  38. JwtBuilder builder = Jwts.builder().setId(id)
  39. .setIssuedAt(now);
  40. if(subject!=null){
  41. builder.setSubject(subject);
  42. }
  43. if(issuer!=null){
  44. builder.setIssuer(issuer);
  45. }
  46. builder .signWith(signatureAlgorithm, signingKey);
  47.  
  48. if (ttlMillis >= 0) {
  49. long expMillis = nowMillis + ttlMillis;
  50. Date exp = new Date(expMillis);
  51. builder.setExpiration(exp);
  52. }
  53. return builder.compact();
  54. }
  55.  
  56. public String updateToken(String token){
  57. try {
  58. Claims claims=verifyToken(token);
  59. String id=claims.getId();
  60. String subject=claims.getSubject();
  61. String issuer=claims.getIssuer();
  62. Date date = claims.getExpiration();
  63. return generToken(id, issuer, subject);
  64. }catch (Exception ex){
  65. ex.printStackTrace();
  66. }
  67. return "0";
  68. }
  69.  
  70. public String updateTokenBase64Code(String token) {
  71. BASE64Encoder base64Encoder=new BASE64Encoder();
  72. BASE64Decoder decoder = new BASE64Decoder();
  73. try {
  74. token=new String(decoder.decodeBuffer(token),"utf-8");
  75. Claims claims=verifyToken(token);
  76. String id=claims.getId();
  77. String subject=claims.getSubject();
  78. String issuer=claims.getIssuer();
  79. Date date = claims.getExpiration();
  80. String newToken = generToken(id, issuer, subject);
  81. return base64Encoder.encode(newToken.getBytes());
  82. }catch (Exception ex){
  83. ex.printStackTrace();
  84. }
  85. return "0";
  86. }
  87.  
  88. public static Claims verifyToken(String token){
  89. Claims claims = Jwts.parser()
  90. .setSigningKey(DatatypeConverter.parseBase64Binary(sercetKey))
  91. .parseClaimsJws(token).getBody();
  92. return claims;
  93. }
  94. }

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

登陆的控制方法:

  1. @RequestMapping("/login")
  2. public String login(String name,String password, Model model){
  3. if(name==null || password==null){
  4. return "error";
  5. }
  6. String token = jwtUtil.generToken("xiaoming",null,null);
  7. model.addAttribute("token", token);
  8. return "redirect:/api/liu";
  9.  
  10. }

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

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

  1.  

springmvc跨域+token验证的更多相关文章

  1. springmvc跨域+token验证(app后台框架搭建二)

    这是app后台框架搭建的第二课,主要针对app应用是跨域的运用,讲解怎么配置跨域服务:其次讲解怎么进行token验证,通过拦截器设置token验证和把token设置到http报文中.主要有如下:   ...

  2. SpringMVC跨域问题排查以及源码实现

    SpringMVC跨域问题排查以及源码实现 最近一次项目中,将SpringMVC版本从4.1.1升级到4.3.10,出现跨域失败的情况.关于同源策略和跨域解决方案,网上有很多资料. 项目采用的方式是通 ...

  3. c#关于JWT跨域身份验证解决方案

    学习程序,不是记代码,而是学习一种思想,以及对代码的理解和思考. JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案.为了网络应用环境间传递声明而执行的一种基于JSON的开发标准 ...

  4. JWT跨域身份验证解决方案

    JSON Web Token(JWT)是目前最流行的跨域身份验证解决方案.本文介绍JWT的原理和用法. 1. 当前跨域身份验证的问题 Internet服务无法与用户身份验证分开.一般过程如下.1.用户 ...

  5. SpringMvc跨域支持

    SpringMvc跨域支持 在controller层加上注解@CrossOrigin可以实现跨域 该注解有两个参数 1,origins  : 允许可访问的域列表 2,maxAge:飞行前响应的缓存持续 ...

  6. SpringMvc 跨域处理

    导读 由于浏览器对于JavaScript的同源策略的限制,导致A网站(Ajax请求)不能通过JS去访问B网站的数据,于是跨域问题就出现了. 跨域指的是域名.端口.协议的组合不同就是跨域. http:/ ...

  7. 关于springmvc跨域

    spingMVC 3.X跨域 关于跨域问题,主要用的比较多的是cros跨域. 详细介绍请看https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Acces ...

  8. springmvc跨域

    //mvc默认是text/plain;charset=ISO-8859-1@RequestMapping(value = "/xxx", produces = "appl ...

  9. springmvc跨域(转)

    跨域资源共享 CORS 详解  原文链接:http://www.ruanyifeng.com/blog/2016/04/cors.html   作者: 阮一峰 日期: 2016年4月12日 CORS是 ...

随机推荐

  1. 交叉编译iperf源代码

    <Iperf简介> Iperf 是一个网络性能测试工具.Iperf可以测试最大TCP和UDP带宽性能,具有多种参数和UDP特性,可以根据需要调整,可以报告带宽.延迟抖动和数据包丢失. &l ...

  2. uoj386 【UNR #3】鸽子固定器

    link (似乎很久没写题解了) 题意: n个物品,每个物品有a,b两个值,给定A,B,现在最多选其中m个,要求最大化选出的物品中[b权值和的B次方-a极差的A次方]. $n\leq 2\times ...

  3. vmware10上三台虚拟机的Hadoop2.5.1集群搭建

    由于官方版本的Hadoop是32位,若在64位Linux上安装,则必须先重新在64位环境下编译Hadoop源代码.本环境采用编译后的hadoop2.5.1 . 安装参考博客: 1 http://www ...

  4. [转]android中drawable资源的解释及例子

    原文链接:         http://blog.csdn.net/wode_dream/article/details/38584693 文章中的内容参考Dev Guide中的Drawable R ...

  5. zoj 2966 Build The Electric System 最小生成树

    Escape Time II Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://acm.zju.edu.cn/onlinejudge/showP ...

  6. AJAX传递数组

    在前台中Jq代码中中用JSON.stringify()将数组转换成 JSON字符串.在后台用json_decode()将JSON字符串转换成数组. 1.JSON.stringify(value [, ...

  7. win2003服务器装spl2008,打安全补丁后无法进入SQL Server Management Studio

    解决方法就是:卸载垃圾的360安全卫士,用windows自带的更新工具更新系统补丁,就好了

  8. Practice safe dc/dc converter

    Short-circuit protection is an obvious requirement for a power supply, especially when its load conn ...

  9. Si4455 低电流 Sub-GHz收发器

    Silicon Labs 的 Si4455 是易于使用的低电流 Sub-GHz EZRadio® 收发器.覆盖所有主要波段,结合了即插即用的简单性和需要处理各种不同应用的灵活性.紧凑的 3 mm x ...

  10. Eclipse配置Struts2问题:ClassNotFoundException: org...dispatcher.ng.filter.StrutsPrepareAndExecuteFilter

    我的解决方案 一开始,我是依照某本教材,配置了User Libraries(名为struts-2.2.3, 可供多个项目多次使用), 然后直接把struts-2.2.3引入过来(这个包不会真正的放在项 ...