SpringMVC 集成 JWT验证方式

JWT官网: https://jwt.io/

这里以java的ssm框架为例,集成jwt。

1.pom.xml 导入jwt的包

<!-- jwt -->
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>2.2.0</version>
</dependency>

2.编写jwt的工具类,包含加密解密功能

import com.auth0.jwt.JWTSigner;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.internal.com.fasterxml.jackson.databind.ObjectMapper;

import java.util.HashMap;
import java.util.Map;

public class JWT {
    private static final String SECRET = "XX#$%()(#*!()!KL<><MQLMNQNQJQK sdfkjsdrow32234545fdf>?N<:{LWPW";

    private static final String EXP = "exp";

    private static final String PAYLOAD = "payload";

    //加密,传入一个对象和有效期
    public static <T> String sign(T object, long maxAge) {
        try {
            final JWTSigner signer = new JWTSigner(SECRET);
            final Map<String, Object> claims = new HashMap<String, Object>();
            ObjectMapper mapper = new ObjectMapper();
            String jsonString = mapper.writeValueAsString(object);
            claims.put(PAYLOAD, jsonString);
            claims.put(EXP, System.currentTimeMillis() + maxAge);
            return signer.sign(claims);
        } catch(Exception e) {
            return null;
        }
    }

    //解密,传入一个加密后的token字符串和解密后的类型
    public static<T> T unsign(String jwt, Class<T> classT) {
        final JWTVerifier verifier = new JWTVerifier(SECRET);
        try {
            final Map<String,Object> claims= verifier.verify(jwt);
            if (claims.containsKey(EXP) && claims.containsKey(PAYLOAD)) {
                long exp = (Long)claims.get(EXP);
                long currentTimeMillis = System.currentTimeMillis();
                if (exp > currentTimeMillis) {
                    String json = (String)claims.get(PAYLOAD);
                    ObjectMapper objectMapper = new ObjectMapper();
                    return objectMapper.readValue(json, classT);
                }
            }
            return null;
        } catch (Exception e) {
            return null;
        }
    }
}

3.jwt有了,ssm要如何去利用,用户验证的第一步是登录,登录时根据用户传来的username和password到数据库验证身份,如果合法,便给该用户jwt加密生成token

    //处理登录
    @RequestMapping(value="login", produces = "application/json; charset=utf-8")
    public @ResponseBody ResponseData login(HttpServletRequest request, @RequestParam( "email") String email,
            @RequestParam("password") String password) {
        Login login = new Login();
        login.setEmail(email);
        login.setPassword(password);
        ResponseData responseData = ResponseData.ok();
        //先到数据库验证
        Integer loginId = userService.checkLogin(login);
        if(null != loginId) {
            User user = userService.getUserByLoginId(loginId);
            login.setId(loginId);
            //给用户jwt加密生成token
            String token = JWT.sign(login, 60L* 1000L* 30L);
            //封装成对象返回给客户端
            responseData.putDataValue("loginId", login.getId());
            responseData.putDataValue("token", token);
            responseData.putDataValue("user", user);
        }
        else{
            responseData =  ResponseData.customerError();
        }
        return responseData;
    }

4.在用户登录时,把loginId和token返回给前台,以后用户每次请求时,都得带上这两个参数,后台拿到token后解密出loginId,与用户传递过来的loginId比较,如果相同,则说明用户身份合法。因为是每个登录过后的每个请求,这里用springmvc的拦截器做

<mvc:interceptors>
    <mvc:interceptor>
        <!-- 匹配的是url路径, 如果不配置或/**,将拦截所有的Controller -->
        <mvc:mapping path="/**" />
        <!-- /register 和 /login 不需要拦截-->
        <mvc:exclude-mapping path="/register" />
        <mvc:exclude-mapping path="/login" />
        <bean class="com.xforce.charles.interceptor.TokenInterceptor"></bean>
    </mvc:interceptor>
    <!-- 当设置多个拦截器时,先按顺序调用preHandle方法,然后逆序调用每个拦截器的postHandle和afterCompletion方法 -->
</mvc:interceptors>

5.拦截器代码

import java.io.PrintWriter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.fastjson.JSONObject;
import com.xforce.charles.model.Admin;
import com.xforce.charles.model.Login;
import com.xforce.charles.util.JWT;
import com.xforce.charles.util.ResponseData;

public class TokenInterceptor implements HandlerInterceptor{

    public void afterCompletion(HttpServletRequest request,
            HttpServletResponse response, Object handler, Exception arg3)
            throws Exception {
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response,
            Object handler, ModelAndView model) throws Exception {
    }

    //拦截每个请求
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
            Object handler) throws Exception {
        response.setCharacterEncoding("utf-8");
        String token = request.getParameter("token");
        ResponseData responseData = ResponseData.ok();
        //token不存在
        if(null != token) {
            Login login = JWT.unsign(token, Login.class);
            String loginId = request.getParameter("loginId");
            //解密token后的loginId与用户传来的loginId不一致,一般都是token过期
            if(null != loginId && null != login) {
                if(Integer.parseInt(loginId) == login.getId()) {
                    return true;
                } else {
                    responseData = ResponseData.forbidden();
                    responseMessage(response, response.getWriter(), responseData);
                    return false;
                }
            } else {
                responseData = ResponseData.forbidden();
                responseMessage(response, response.getWriter(), responseData);
                return false;
            }
        } else {
            responseData = ResponseData.forbidden();
            responseMessage(response, response.getWriter(), responseData);
            return false;
        }
    }

    //请求不通过,返回错误信息给客户端
    private void responseMessage(HttpServletResponse response, PrintWriter out, ResponseData responseData) {
        responseData = ResponseData.forbidden();
        response.setContentType("application/json; charset=utf-8");
        String json = JSONObject.toJSONString(responseData);
        out.print(json);
        out.flush();
        out.close();
    }

}

6.注意点:用@ResponseBody返回json数据时,有时会有乱码,需要在springmvc的配置文件里面加以下配置(spring4以上)

<mvc:annotation-driven>
   <mvc:message-converters register-defaults="true">
    <bean class="org.springframework.http.converter.StringHttpMessageConverter">
      <property name="supportedMediaTypes" value = "text/plain;charset=UTF-8" />
    </bean>
   </mvc:message-converters>
</mvc:annotation-driven> 

7.最后分享一个类,用于返回给客户端的万能类,我觉得它可以满足一般的接口

import java.util.HashMap;
import java.util.Map;

public class ResponseData {

    private final String message;
    private final int code;
    private final Map<String, Object> data = new HashMap<String, Object>();

    public String getMessage() {
        return message;
    }

    public int getCode() {
        return code;
    }

    public Map<String, Object> getData() {
        return data;
    }

    public ResponseData putDataValue(String key, Object value) {
        data.put(key, value);
        return this;
    }

    private ResponseData(int code, String message) {
        this.code = code;
        this.message = message;
    }

    public static ResponseData ok() {
        return new ResponseData(200, "Ok");
    }

    public static ResponseData notFound() {
        return new ResponseData(404, "Not Found");
    }

    public static ResponseData badRequest() {
        return new ResponseData(400, "Bad Request");
    }

    public static ResponseData forbidden() {
        return new ResponseData(403, "Forbidden");
    }

    public static ResponseData unauthorized() {
        return new ResponseData(401, "unauthorized");
    }

    public static ResponseData serverInternalError() {
        return new ResponseData(500, "Server Internal Error");
    }

    public static ResponseData customerError() {
        return new ResponseData(1001, "customer Error");
    }
}

原文地址:https://www.cnblogs.com/ifindu-san/p/9890879.html

时间: 2024-10-10 15:02:46

SpringMVC 集成 JWT验证方式的相关文章

Spring Cloud系列-Zuul网关集成JWT身份验证

前言 这两三年项目中一直在使用比较流行的spring cloud框架,也算有一定积累,打算有时间就整理一些干货与大家分享. 本次分享zuul网关集成jwt身份验证 业务背景 项目开发少不了身份认证,jwt作为当下比较流行的身份认证方式之一主要的特点是无状态,把信息放在客户端,服务器端不需要保存session,适合分布式系统使用. 把jwt集成在网关的好处是业务工程不需要关心身份验证,专注业务逻辑(网关可验证token后,把解析出来的身份信息如userId,放在请求头传递给业务工程). 顺便分享下

spring+springMVC集成(annotation方式)

spring+springMVC集成(annotation方式) SpringMVC+Spring4.0+Hibernate 简单的整合 MyBatis3整合Spring3.SpringMVC3

springMVC系列之(三) spring+springMVC集成(annotation方式)

个人认为使用框架并不是很难,关键要理解其思想,这对于我们提高编程水平很有帮助.不过,如果用都不会,谈思想就变成纸上谈兵了!!!先技术,再思想.实践出真知. 1.基本概念 1.1.Spring Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来.它是为了解决企业应用开发的复杂性而创建的.Spring使用

Springmvc集成Shiro实现权限管理

Shiro是一个安全框架,他可以集成其他开发开发框架 如:Springmvc,实现用户身份认证.权限管理等等功能,shiro详细的介绍也就不讲了,这里给出一些关键的知识点吧: 知识点: shiro中默认的过滤器 过滤器名称 过滤器类 描述 anon org.apache.shiro.web.filter.authc.AnonymousFilter 匿名过滤器 authc org.apache.shiro.web.filter.authc.FormAuthenticationFilter 如果继续

Integrated Security 身份验证方式

server=localhost;database=Northwind; integrated security=SSPI Microsoft安全支持提供器接口(SSPI)是定义得较全面的公用API,用来获得验证.信息完整性.信息隐私等集成安全服务,以及用于所有分布式应用程序协议的安全方面的服务.应用程序协议设计者能够利用该接口获得不同的安全性服务而不必修改协议本身. Integrated Security 身份验证方式 当为false时,将在连接中指定用户ID和密码. 当为true时,将使用当

服务器身份验证方式

服务器身份验证方式: 1.是基于Cookie的身份验证,使用服务器端的cookie来对每次请求的用户进行身份验证. 2. 较新的方法,基于令牌Token-Based的认证,依赖于被发送到服务器上每个请求的签署令牌. 为什么基于令牌token-based的方式更好呢?理由如下:1.跨域 / CORS: cookies + CORS 并不能跨不同的域名.而基于令牌能够使用 AJAX 调用服务器,在任何域名下你都可以使用HTTP header头部来传输用户信息. 2. 无态(代表服务器端可伸缩): 没

如何更改SQL Server 2008 登陆验证方式

配置SQL Server的身份验证方式 在 默认情况下,SQL Server 2005 Express是采用集成的Windows安全验证且禁用了sa登录名.为了工作组环境下不使用不方便的 Windows集成安全验证,我们要启用SQL Server 2005 Express的混合安全验证,也就是说由SQL Server来验证用户而不 是由Windows来验证用户. 1.使用SQL Server Management Studio Express. 当 我们启动SQL Server Manageme

WebService的几种验证方式

转 http://www.cnblogs.com/yoshiki1895/archive/2009/06/03/1495440.html WebService的几种验证方式 1.1      WebService设计 1.1.1   传输基本参数 1.1.2   传输数据集合 (1)     数组 (2)     DataSet 1.2      WebService异常处理 1.3      WebService性能 1.4      WebService认证 请参考WebService认证学

事无巨细-全方位跟踪配置Exchange ActvieSync使用证书验证方式

前两段话为费话,请节约时间的人绕行. 工作中需要用到Exchange ActiveSync证书认证的方式,问了同事们没有一个会做,公司的ActiveSync也只是用到了Basic authentication, 而且都是由国外的同事维护的.没办法只好自己来了,可是不料在国内网站上只找到一些很少的片断,不全面也不系统,对于我这样的小白来说,看了之后只会越来越糊涂.在微软的官网上倒是很全面,但是被分成了多个主题,每个功能和配置点都有很多种情况,对于自己想要做的却很难挑出针对性的内容,微软的这种帮助文