• Json web token


    转载自:https://blog.csdn.net/zsg88/article/details/76892551

    下面我们用springmvc和jwt的类库来实现一个例子。

    要使用jwt,需要pom.xml中添加如下依赖

    [java] view plain copy
     
    1. <dependency>  
    2.     <groupId>com.auth0</groupId>  
    3.     <artifactId>java-jwt</artifactId>  
    4.     <version>3.2.0</version>  
    5. </dependency>  

    下面贴一个完整的pom.xml

    [html] view plain copy
     
    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <project xmlns="http://maven.apache.org/POM/4.0.0"  
    3.          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    4.          xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">  
    5.     <modelVersion>4.0.0</modelVersion>  
    6.   
    7.     <groupId>org.jstudioframework</groupId>  
    8.     <artifactId>jstudio-jwt</artifactId>  
    9.     <version>1.0-SNAPSHOT</version>  
    10.   
    11.     <properties>  
    12.         <!-- 设置编码字符集 -->  
    13.         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>  
    14.         <!-- 集中定义依赖版本号 -->  
    15.         <junit.version>4.12</junit.version>  
    16.         <spring.version>4.3.7.RELEASE</spring.version>  
    17.         <jackson.version>2.8.4</jackson.version>  
    18.         <java.jwt.version>3.2.0</java.jwt.version>  
    19.         <jstl.version>1.2</jstl.version>  
    20.         <servlet-api.version>2.5</servlet-api.version>  
    21.         <jsp-api.version>2.2</jsp-api.version>  
    22.     </properties>  
    23.   
    24.     <dependencies>  
    25.         <dependency>  
    26.             <groupId>junit</groupId>  
    27.             <artifactId>junit</artifactId>  
    28.             <version>${junit.version}</version>  
    29.             <scope>test</scope>  
    30.         </dependency>  
    31.         <dependency>  
    32.             <groupId>com.auth0</groupId>  
    33.             <artifactId>java-jwt</artifactId>  
    34.             <version>${java.jwt.version}</version>  
    35.         </dependency>  
    36.         <dependency>  
    37.             <groupId>com.fasterxml.jackson.core</groupId>  
    38.             <artifactId>jackson-databind</artifactId>  
    39.             <version>${jackson.version}</version>  
    40.         </dependency>  
    41.         <dependency>  
    42.             <groupId>com.fasterxml.jackson.core</groupId>  
    43.             <artifactId>jackson-core</artifactId>  
    44.             <version>${jackson.version}</version>  
    45.         </dependency>  
    46.         <dependency>  
    47.             <groupId>org.springframework</groupId>  
    48.             <artifactId>spring-core</artifactId>  
    49.             <version>${spring.version}</version>  
    50.         </dependency>  
    51.         <dependency>  
    52.             <groupId>org.springframework</groupId>  
    53.             <artifactId>spring-beans</artifactId>  
    54.             <version>${spring.version}</version>  
    55.         </dependency>  
    56.         <dependency>  
    57.             <groupId>org.springframework</groupId>  
    58.             <artifactId>spring-context</artifactId>  
    59.             <version>${spring.version}</version>  
    60.         </dependency>  
    61.         <dependency>  
    62.             <groupId>org.springframework</groupId>  
    63.             <artifactId>spring-context-support</artifactId>  
    64.             <version>${spring.version}</version>  
    65.         </dependency>  
    66.         <dependency>  
    67.             <groupId>org.springframework</groupId>  
    68.             <artifactId>spring-web</artifactId>  
    69.             <version>${spring.version}</version>  
    70.         </dependency>  
    71.         <dependency>  
    72.             <groupId>org.springframework</groupId>  
    73.             <artifactId>spring-webmvc</artifactId>  
    74.             <version>${spring.version}</version>  
    75.         </dependency>  
    76.         <!-- JSP相关 -->  
    77.         <dependency>  
    78.             <groupId>javax.servlet</groupId>  
    79.             <artifactId>jstl</artifactId>  
    80.             <version>${jstl.version}</version>  
    81.         </dependency>  
    82.         <dependency>  
    83.             <groupId>javax.servlet</groupId>  
    84.             <artifactId>servlet-api</artifactId>  
    85.             <version>${servlet-api.version}</version>  
    86.             <scope>provided</scope>  
    87.         </dependency>  
    88.         <dependency>  
    89.             <groupId>javax.servlet.jsp</groupId>  
    90.             <artifactId>jsp-api</artifactId>  
    91.             <version>${jsp-api.version}</version>  
    92.             <scope>provided</scope>  
    93.         </dependency>  
    94.     </dependencies>  
    95.   
    96.     <build>  
    97.         <!-- 配置插件 -->  
    98.         <plugins>  
    99.             <plugin>  
    100.                 <groupId>org.apache.tomcat.maven</groupId>  
    101.                 <artifactId>tomcat7-maven-plugin</artifactId>  
    102.                 <configuration>  
    103.                     <port>8080</port>  
    104.                     <path>/</path>  
    105.                     <url>http://127.0.0.1:8080/manager/text</url>  
    106.                     <username>tomcat</username>  
    107.                     <password>tomcat</password>  
    108.                 </configuration>  
    109.             </plugin>  
    110.         </plugins>  
    111.     </build>  
    112. </project>  



    一。定义一个jwt的工具类,具有加密和解密token的功能

    [java] view plain copy
     
    1. import java.util.HashMap;  
    2. import java.util.Map;  
    3.   
    4. /** 
    5.  * JwtToken 
    6.  */  
    7. public class JwtToken {  
    8.   
    9.     //密钥  
    10.     private static final String SECRET = "secret";  
    11.   
    12.     //jackson  
    13.     private static ObjectMapper mapper = new ObjectMapper();  
    14.   
    15.     /** 
    16.      * header数据 
    17.      * @return 
    18.      */  
    19.     private static Map<String, Object> createHead() {  
    20.         Map<String, Object> map = new HashMap<String, Object>();  
    21.         map.put("typ", "JWT");  
    22.         map.put("alg", "HS256");  
    23.         return map;  
    24.     }  
    25.   
    26.     /** 
    27.      * 生成token 
    28.      * 
    29.      * @param obj    对象数据 
    30.      * @param maxAge 有效期 
    31.      * @param <T> 
    32.      * @return 
    33.      */  
    34.     public static <T> String sign(T obj, long maxAge) throws UnsupportedEncodingException, JsonProcessingException {  
    35.         JWTCreator.Builder builder = JWT.create();  
    36.   
    37.         builder.withHeader(createHead())//header  
    38.                 .withSubject(mapper.writeValueAsString(obj));  //payload  
    39.   
    40.         if (maxAge >= 0) {  
    41.             long expMillis = System.currentTimeMillis() + maxAge;  
    42.             Date exp = new Date(expMillis);  
    43.             builder.withExpiresAt(exp);  
    44.         }  
    45.   
    46.         return builder.sign(Algorithm.HMAC256(SECRET));  
    47.     }  
    48.   
    49.     /** 
    50.      * 解密 
    51.      * @param token   token字符串 
    52.      * @param classT  解密后的类型 
    53.      * @param <T> 
    54.      * @return 
    55.      */  
    56.     public static <T> T unsign(String token, Class<T> classT) throws IOException {  
    57.         JWTVerifier verifier = JWT.require(Algorithm.HMAC256(SECRET)).build();  
    58.         DecodedJWT jwt = verifier.verify(token);  
    59.   
    60.         Date exp = jwt.getExpiresAt();  
    61.         if(exp!=null&&exp.after(new Date())){  
    62.             String subject = jwt.getSubject();  
    63.             return mapper.readValue(subject, classT);  
    64.         }  
    65.   
    66.         return null;  
    67.     }  
    68.   
    69. }  



    二。 登录时根据用户传来的username和password验证身份,如果合法,便给该用户jwt加密生成token

    [java] view plain copy
     
    1. package jwt.controller;  
    2.   
    3. import com.fasterxml.jackson.core.JsonProcessingException;  
    4. import jwt.JwtToken;  
    5. import jwt.model.User;  
    6. import jwt.util.ResponseEntity;  
    7. import org.springframework.stereotype.Controller;  
    8. import org.springframework.web.bind.annotation.RequestMapping;  
    9. import org.springframework.web.bind.annotation.RequestParam;  
    10. import org.springframework.web.bind.annotation.ResponseBody;  
    11.   
    12. import javax.servlet.http.HttpServletRequest;  
    13. import java.io.UnsupportedEncodingException;  
    14.   
    15. /** 
    16.  * 用户登录 
    17.  */  
    18.   
    19. @Controller  
    20. public class LoginController {  
    21.   
    22.     @RequestMapping(value="login", produces = "application/json; charset=utf-8")  
    23.     @ResponseBody  
    24.     public ResponseEntity login(HttpServletRequest request, @RequestParam( "username") String username,  
    25.                                 @RequestParam("password") String password) throws UnsupportedEncodingException, JsonProcessingException {  
    26.         ResponseEntity responseEntity = ResponseEntity.ok();  
    27.   
    28.         if("admin".equals(username) && "admin".equals(password)) {  
    29.             //模拟用户数据,真实环境需要到数据库验证  
    30.             User user = new User();  
    31.             user.setId(123456);  
    32.             user.setUsername(username);  
    33.             //给用户jwt加密生成token  
    34.             String token = JwtToken.sign(user, 60L * 1000L * 30L);  
    35.             //封装成对象返回给客户端  
    36.             responseEntity.putDataValue("userId", user.getId());  
    37.             responseEntity.putDataValue("token", token);  
    38.             responseEntity.putDataValue("user", user);  
    39.         }  
    40.         else{  
    41.             responseEntity =  ResponseEntity.customerError();  
    42.         }  
    43.         return responseEntity;  
    44.     }  
    45.   
    46. }  

    User用户类如下

    [java] view plain copy
     
    1. package jwt.model;  
    2.   
    3. /** 
    4.  * User bean 
    5.  */  
    6. public class User {  
    7.     private long id;  
    8.     private String username;  
    9.     private String password;  
    10.   
    11.     public long getId() {  
    12.         return id;  
    13.     }  
    14.   
    15.     public void setId(long id) {  
    16.         this.id = id;  
    17.     }  
    18.   
    19.     public String getUsername() {  
    20.         return username;  
    21.     }  
    22.   
    23.     public void setUsername(String username) {  
    24.         this.username = username;  
    25.     }  
    26.   
    27.     public String getPassword() {  
    28.         return password;  
    29.     }  
    30.   
    31.     public void setPassword(String password) {  
    32.         this.password = password;  
    33.     }  
    34. }  



    返回给用户端的一个工具类

    [java] view plain copy
     
    1. package jwt.util;  
    2.   
    3. import java.util.HashMap;  
    4. import java.util.Map;  
    5.   
    6. public class ResponseEntity {  
    7.   
    8.     public static final String ERRORS_KEY = "errors";  
    9.   
    10.     private final String message;  
    11.     private final int code;  
    12.     private final Map<String, Object> data = new HashMap();  
    13.   
    14.     public String getMessage() {  
    15.         return message;  
    16.     }  
    17.   
    18.     public int getCode() {  
    19.         return code;  
    20.     }  
    21.   
    22.     public Map<String, Object> getData() {  
    23.         return data;  
    24.     }  
    25.   
    26.     public ResponseEntity putDataValue(String key, Object value) {  
    27.         data.put(key, value);  
    28.         return this;  
    29.     }  
    30.   
    31.     private ResponseEntity(int code, String message) {  
    32.         this.code = code;  
    33.         this.message = message;  
    34.     }  
    35.   
    36.     public static ResponseEntity ok() {  
    37.         return new ResponseEntity(200, "Ok");  
    38.     }  
    39.   
    40.     public static ResponseEntity notFound() {  
    41.         return new ResponseEntity(404, "Not Found");  
    42.     }  
    43.   
    44.     public static ResponseEntity badRequest() {  
    45.         return new ResponseEntity(400, "Bad Request");  
    46.     }  
    47.   
    48.     public static ResponseEntity forbidden() {  
    49.         return new ResponseEntity(403, "Forbidden");  
    50.     }  
    51.   
    52.     public static ResponseEntity unauthorized() {  
    53.         return new ResponseEntity(401, "unauthorized");  
    54.     }  
    55.   
    56.     public static ResponseEntity serverInternalError() {  
    57.         return new ResponseEntity(500, "Server Internal Error");  
    58.     }  
    59.   
    60.     public static ResponseEntity customerError() {  
    61.         return new ResponseEntity(1001, "Customer Error");  
    62.     }  
    63. }  



    三。在用户登录后获得userId和token,以后用户每次请求时,都得带上这两个参数,后台拿到token后解密出userId,与用户传递过来的userId比较,如果相同,则说明用户身份合法。这里用springmvc的拦截器实现验证。

    注意:测试使用Params传递参数的,建议正式环境在header里添加参数

    [java] view plain copy
     
    1. package jwt.interceptor;  
    2.   
    3. import com.fasterxml.jackson.databind.ObjectMapper;  
    4. import jwt.JwtToken;  
    5. import jwt.model.User;  
    6. import jwt.util.ResponseEntity;  
    7. import org.springframework.web.servlet.HandlerInterceptor;  
    8. import org.springframework.web.servlet.ModelAndView;  
    9.   
    10. import javax.servlet.http.HttpServletRequest;  
    11. import javax.servlet.http.HttpServletResponse;  
    12. import java.io.PrintWriter;  
    13.   
    14. /** 
    15.  * Token验证拦截器 
    16.  */  
    17. public class UserTokenInterceptor implements HandlerInterceptor {  
    18.   
    19.     public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object o) throws Exception {  
    20.         String token = request.getParameter("token");  
    21.         ResponseEntity responseData = ResponseEntity.ok();  
    22.         //token不存在  
    23.         if (token != null) {  
    24.             User user = JwtToken.unsign(token, User.class);  
    25.             String userId = request.getParameter("userId");  
    26.             //解密token后的userId与用户传来的userId不一致,大多是因为token过期  
    27.             if (user != null && userId != null && Integer.parseInt(userId) == user.getId()) {  
    28.                 return true;  
    29.             }  
    30.         }  
    31.   
    32.         responseData = ResponseEntity.forbidden();  
    33.         response.setContentType("application/json; charset=utf-8");  
    34.         ObjectMapper mapper = new ObjectMapper();  
    35.         String json = mapper.writeValueAsString(responseData);  
    36.         PrintWriter out = response.getWriter();  
    37.         out.print(json);  
    38.         out.flush();  
    39.         out.close();  
    40.         return false;  
    41.     }  
    42.   
    43.     public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {  
    44.   
    45.     }  
    46.   
    47.     public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {  
    48.   
    49.     }  
    50. }  


    四。springmvc的配置

    [html] view plain copy
     
    1. <?xml version="1.0" encoding="UTF-8"?>  
    2. <beans xmlns="http://www.springframework.org/schema/beans"  
    3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    4.        xmlns:context="http://www.springframework.org/schema/context"  
    5.        xmlns:mvc="http://www.springframework.org/schema/mvc"  
    6.        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd  
    7.        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd  
    8.         http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">  
    9.   
    10.     <context:component-scan base-package="jwt.controller"/>  
    11.   
    12.     <mvc:annotation-driven />  
    13.   
    14.     <!-- 拦截器设置 -->  
    15.     <mvc:interceptors>  
    16.         <mvc:interceptor>  
    17.             <!-- 匹配的是url路径, 如果不配置或/**,将拦截所有的Controller -->  
    18.             <mvc:mapping path="/**" />  
    19.             <!-- /register 和 /login 不需要拦截-->  
    20.             <mvc:exclude-mapping path="/register" />  
    21.             <mvc:exclude-mapping path="/login" />  
    22.             <bean class="jwt.interceptor.UserTokenInterceptor"></bean>  
    23.         </mvc:interceptor>  
    24.         <!-- 当设置多个拦截器时,先按顺序调用preHandle方法,然后逆序调用每个拦截器的postHandle和afterCompletion方法 -->  
    25.     </mvc:interceptors>  
    26.   
    27.     <!-- 默认的视图解析器 在上边的解析错误时使用 (默认使用html)- -->  
    28.     <bean id="defaultViewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">  
    29.         <property name="viewClass" value="org.springframework.web.servlet.view.JstlView"/>  
    30.         <property name="contentType" value="text/html"/>  
    31.         <property name="prefix" value="/WEB-INF/jsp/"/>  
    32.         <property name="suffix" value=".jsp"/>  
    33.         <property name="order" value="1"/>  
    34.     </bean>  
    35.   
    36. </beans>  

    五。 使用Chrome插件Postman进行简单的测试

    1.登录,http://localhost:8080/login

    记下 token和userId

    2. 测试token鉴权  http://localhost:8080/info

    输入正确的userId和token

    注意:测试使用Params传递参数的,建议正式环境在header里添加参数

    输入错误的userId或token,在拦截器那里就被拦截了

  • 相关阅读:
    数组和类集排序总结
    toString()方法
    冒泡排序java
    Scanner类输入字符串和整形数字
    身份证分组
    jsonp的实质
    在伪数组上部署iterator方法
    获取属性的方法
    合并以及对于引用克隆
    深度复制对象已解决循环引用
  • 原文地址:https://www.cnblogs.com/jay36/p/8716445.html
Copyright © 2020-2023  润新知