• JWT学习


    参考文章:https://www.jianshu.com/p/576dbf44b2ae

    JWT

    1、什么是JSON WEB TOKEN?

    JSON Web令牌(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑而独立的方法,用于在各方之间安全地将信息作为JSON对象传输。由于此信息是经过数字签名的,因此可以被验证和信任。可以使用秘密(使用HMAC算法)或使用RSA或ECDSA的公用/专用密钥对对JWT进行签名。尽管可以对JWT进行加密以提供双方之间的保密性,但我们将重点关注已签名的令牌。签名的令牌可以验证其中包含的声明的完整性,而加密的令牌则将这些声明隐藏在其他方的面前。当使用公钥/私钥对对令牌进行签名时,签名还证明只有持有私钥的一方才是对其进行签名的一方。

    2、什么时候我们应该使用JWT?

    • 授权:这是使用JWT的最常见方案。一旦用户登录,每个后续请求将包括JWT,从而允许用户访问该令牌允许的路由,服务和资源。单点登录是当今广泛使用JWT的一项功能,因为它的开销很小并且可以在不同的域中轻松使用。
    • 信息交换:JSON Web令牌是在各方之间安全传输信息的一种好方法。因为可以对JWT进行签名(例如,使用公钥/私钥对),所以您可以确定发件人是他们所说的人。此外,由于签名是使用标头和有效负载计算的,因此您还可以验证内容是否遭到篡改。

    3、JWT的结构组成

    • Header 头部
    • Payload 负载
    • Signature 签名

    组成:xxxxx.yyyyy.zzzzz

    3.1 Header

    Header通常由两部分组成:令牌的类型(即JWT)和所使用的签名算法,例如HMAC SHA256或RSA。

    //for example
    {
      "alg": "HS256",		//签名算法
      "typ": "JWT"			//令牌的类型
    }
    //这个header一般去改变它
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    然后,此JSON被Base64Url编码以形成JWT的第一部分.

    3.2 Payload

    令牌的第二部分是有效负载,其中包含声明。声明是有关实体(通常是用户)和其他数据的声明。共有三种类型的声明:registered public, and private claims.。

    3.2.1 registered claims:

    这些是一组非强制性的但建议使用的预定义声明,以提供一组有用的可互操作的声明。其中一些是:iss(issuer:发行方),exp(expiration time:到期时间),sub(subject:主题),aud(audience:受众群体)等

    请注意,声明名称仅是三个字符,因为JWT是紧凑的。

    3.2.2 public claims

    这些可以由使用JWT的人员随意定义。但为避免冲突,应在IANA JSON Web令牌注册表中定义它们,或将其定义为包含抗冲突名称空间的URI。

    3.2.3 private claims

    这些是自定义声明,旨在在同意使用它们的各方之间共享信息,并且既不是注册声明也不是公共声明。

    //for example
    {
      "sub": "1234567890",
      "name": "John Doe",
      "admin": true
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    然后对有效负载进行Base64Url编码,以形成JSON Web令牌的第二部分。

    请注意,对于已签名的令牌,此信息尽管可以防止篡改,但任何人都可以读取。除非加密,否则不要将机密信息放入JWT的有效负载或报头元素中

    3.3 Signature

    要创建签名部分,您必须获取编码的报头、编码的有效负载、一个秘密、在报头中指定的算法,并对其进行签名。

    例如,如果要使用HMAC SHA256算法,将按以下方式创建签名:

    //使用HMAC SHA256算法进行加密签名
    HMACSHA256(
      base64UrlEncode(header)		//对header进行base64加密
      + "." +					
      base64UrlEncode(payload),		//对payload进行base64加密
      secret	//秘密,随机盐,这个不能给别人知道
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    签名用于验证消息在整个过程中没有被更改,并且,在使用私钥签名的令牌的情况下,它还可以验证JWT的发送者是它所说的人。


    输出是三个base64url字符串,用点分隔,可以在HTML和HTTP环境中轻松地传递这些字符串,但与基于XML的标准(如SAML)相比,它更紧凑。

    下面显示了一个JWT,它对前一个头和有效负载进行了编码,并用一个秘密进行了签名。

    在这里插入图片描述

    4、基于传统的Session认证

    在这里插入图片描述

    在这里插入图片描述

    5、基于JWT的认证

    在这里插入图片描述

    在这里插入图片描述

    6、使用JWT

    6.1 导入依赖

    <dependency>
        <groupId>com.auth0groupId>
        <artifactId>java-jwtartifactId>
        <version>3.11.0version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    6.2 构建token

    public void test(){
        //生成token
        String token = JWT.create()
            .withHeader(null)   //设置header,一般采用默认值
            .withClaim("name", "zhangsan")  //设置payload
            .withClaim("age", 18)
            .withClaim("sex", "girl")
            .sign(Algorithm.HMAC256("!@#QSDF@#@%¥……%"));    //设置签名,采用HMAC256算法
        System.out.println(token);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    构建token抛出的异常:

    • JWTCreationException //构建token失败时,抛出的异常,非法签名结构,无法转换Claims

    6.3 验证token

    public void test2(){
        //验证token
        JWTVerifier build = JWT.require(Algorithm.HMAC256("!@#QSDF@#@%¥……%")).build();
        //验证token,验证失败会抛出异常
        DecodedJWT verify = build.verify("yJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzZXgiOiJnaXJsIiwibmFtZSI6InpoYW5nc2FuIiwiYWdlIjoxOH0.Cne13wAqFmRgmxgWOKgykGXVSfba5XjS-c4soh83QqQ");
    
        System.out.println(verify.getClaim("name").asString());
        System.out.println(verify.getClaim("age").asInt());
        System.out.println(verify.getClaim("sex").asString());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    随机盐:!@#QSDF@#@%¥……% 随机设置,不能被别人知道,加密和解密保持一致

    加密算法:HMAC256 加密和解密保持一致


    验证token抛出的异常

    在这里插入图片描述

    先验签,后验token。

    7、JWT工具类

    /**
     * JWT工具类
     */
    public class JWTUtils {
    
        //随机盐,随机设置
        private final static String secret = "$%#$%%^FSDFDS@#$@ASDdfg";
    
        /**
         * 根据提供的k-v进行生成token
         * @param payload k-v信息
         * @param expireTime 过期时间,单位:秒
         * @return token
         */
        public static String createToken(Map<String,String> payload, Integer expireTime) {
            Calendar instance = Calendar.getInstance();
            instance.add(Calendar.SECOND,expireTime);
            String token = null;
            try{
                //创建Builder对象
                JWTCreator.Builder builder = JWT.create().withHeader(null); //header
                //payload
                payload.forEach((k,v)->{
                    builder.withClaim(k,v);
                });
                builder.withExpiresAt(instance.getTime());      //过期时间
                token = builder.sign(Algorithm.HMAC256(secret));    //签名
            }catch (JWTCreationException e){
                System.out.println("构建token异常,请检查签名是否合法...");
            }
            return token;
        }
    
        /**
         * 验证token是否合法
         * @param token
         * @return false:验证失败  true:验证合法
         */
        public static boolean verifyJWT(String token){
            try{
                JWT.require(Algorithm.HMAC256(secret)).build().verify(token);
            }catch (JWTVerificationException e){
                return false;
            }
            return true;
        }
    
    
        /**
         * 获取token的数据
         * @return map
         */
        public static Map<String,String> decodeJWT(String token){
            Map<String,String> map = new HashMap<>();
            try{
                DecodedJWT verify = JWT.require(Algorithm.HMAC256(secret)).build().verify(token);
                Map<String, Claim> claims = verify.getClaims();
                claims.forEach((k,v)->{
                    map.put(k,v.asString());
                });
                return map;
            }catch (JWTVerificationException e){
                return null;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66

    8、JWT在WEB中的应用

    1、创建springboot项目,导入依赖

    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-webartifactId>
    dependency>
    
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-testartifactId>
        <scope>testscope>
    dependency>
    
    <dependency>
        <groupId>com.auth0groupId>
        <artifactId>java-jwtartifactId>
        <version>3.11.0version>
    dependency>
    <dependency>
        <groupId>mysqlgroupId>
        <artifactId>mysql-connector-javaartifactId>
        <version>8.0.15version>
    dependency>
    <dependency>
        <groupId>com.baomidougroupId>
        <artifactId>mybatis-plus-boot-starterartifactId>
        <version>3.4.1version>
    dependency>
    
    <dependency>
        <groupId>org.projectlombokgroupId>
        <artifactId>lombokartifactId>
        <version>1.18.12version>
    dependency>
    <dependency>
        <groupId>org.codehaus.jacksongroupId>
        <artifactId>jackson-mapper-aslartifactId>
        <version>1.9.13version>
    dependency>
    <dependency>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-thymeleafartifactId>
    dependency>
    
    <dependency>
        <groupId>org.apache.commonsgroupId>
        <artifactId>commons-lang3artifactId>
        <version>3.7version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    2、配置application.yml

    mybatis-plus:
      type-aliases-package: top.linging.jwt.pojo
      mapper-locations: classpath:top/linging/jwt/mapper/*.xml
      configuration:
        map-underscore-to-camel-case: true
    spring:
      datasource:
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/student?characterEncoding=UTF-8&useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
        username: root
        password: 123456
      thymeleaf:
        prefix: classpath:/templates/
        suffix: .html
        cache: false
    server:
      port: 8082
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    3、编写登录拦截器

    public class LoginInterceptor implements HandlerInterceptor {
    
        /**
         * 获取requestHeader中的token
         * @param request
         * @param response
         * @param handler
         * @return
         * @throws Exception
         */
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            System.out.println("拦截诶器中...............");
            //获取requestHeader中的token
            String token = CookieUtils.getCookieValue(request,"userToken");
            //返回结果
            Map<String, Object> map = new HashMap<>();
            //验证token失败
            if(token == null || !JWTUtils.verifyJWT(token)) {
                map.put("status",false);
                map.put("msg","login fail");
                response.setContentType("application/json;charset=utf-8");
                response.getWriter().println(JsonUtil.mapToJson(map));
                return false;
            }
            //放行
            System.out.println("成功.....");
            return true;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    4、注册拦截器

    @Configuration
    public class WebConfig implements WebMvcConfigurer {
    
        //拦截器对请求进行拦截与放行
        @Override
        public void addInterceptors(InterceptorRegistry registry) {
            registry.addInterceptor(new LoginInterceptor())
                    .addPathPatterns("/user/**")
                    .excludePathPatterns("/user/login")
                    .excludePathPatterns("/router/toLogin");
        }
    
        private CorsConfiguration corsConfig() {
            CorsConfiguration corsConfiguration = new CorsConfiguration();
            // 请求常用的三种配置,*代表允许所有,也可以自定义属性(比如 header 只能带什么,只能是 post 方式等)
            corsConfiguration.addAllowedOrigin("*");
            corsConfiguration.addAllowedHeader("*");
            corsConfiguration.addAllowedMethod("*");
            corsConfiguration.setAllowCredentials(true);
            corsConfiguration.setMaxAge(3600L);
            return corsConfiguration;
        }
    
        //解决跨域
        @Bean
        public CorsFilter corsFilter() {
            UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            source.registerCorsConfiguration("/**", corsConfig());
            return new CorsFilter(source);
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32

    5、编写mapper层

    @Repository
    public interface UserMapper extends BaseMapper<User> {
    }
    
    • 1
    • 2
    • 3

    6、编写service层

    @Service
    @Transactional
    public class UserServiceImpl implements UserService {
    
        @Autowired
        private UserMapper userMapper;
    
        /**
         * 登录
         * @param name
         * @return
         */
        @Override
        public User findUserByName(String name) {
            QueryWrapper<User> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("name",name);
            return userMapper.selectOne(queryWrapper);
        }
    
        /**
         * 需要登录才能访问的api
         * @return
         */
        @Override
        public List<User> findAllUser() {
            return userMapper.selectList(null);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    7、编写controller层

    //@CrossOrigin(value = "*")
    @RestController
    @RequestMapping("/user")
    public class UserController {
    
        @Autowired
        private UserService userService;
    
        //登录的方法
        @PostMapping("/login")
        public Map<String,Object> login(@RequestParam("name") String username,
                                        HttpServletRequest request,
                                        HttpServletResponse response){
            int expireTime = 10;    //过期时间,10s
            System.out.println(username);
            Map<String, String> payload = new HashMap<>();
            payload.put("name",username);
            String token = JWTUtils.createToken(payload,expireTime);
            Map<String, Object> map = new HashMap<>();
            if(token == null){
                map.put("status",false);
                map.put("msg","login fail");
                map.put("token","");
                return map;
            }
            CookieUtils.setCookie(request,response,"userToken",token,expireTime,"",true);
            map.put("status",true);
            map.put("msg","login ok");
            map.put("token",token);
            return map;
        }
    
        //需要登录之后才能访问的方法
        @GetMapping("/list")
        public List<User> findAllUser(){
            return userService.findAllUser();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    用到的工具类:

    /**
     * @ClassName JsonUtil
     * @Description json工具类
     * @Author AlphaJunS
     * @Date 2020/3/27 18:59
     * @Version 1.0
     */
    public class JsonUtil {
    
        /**
         * @Author AlphaJunS
         * @Date 19:06 2020/3/27
         * @Description json转map
         * @param json
         * @return java.util.Map
         */
        public static Map<String,Object> jsonToMap(String json) throws Exception{
            ObjectMapper objectMapper = new ObjectMapper();
            Map<String,Object> map;
            try {
                map = (Map<String,Object>)objectMapper.readValue(json, Map.class);
            } catch (JsonParseException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                throw e;
            } catch (JsonMappingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                throw e;
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                throw e;
            }
            return map;
        }
    
        /**
         * @Author AlphaJunS
         * @Date 19:07 2020/3/27
         * @Description json转List>
         * @param json
         * @return java.util.List>
         */
        public static List<Map<String,?>> jsonToMapList(String json) throws Exception{
            ObjectMapper objectMapper = new ObjectMapper();
            JavaType javaType = objectMapper.getTypeFactory().constructParametricType(List.class, Map.class);
            List<Map<String, ?>> mapList;
            try {
                mapList = (List<Map<String,?>>)objectMapper.readValue(json, javaType);
            } catch (JsonParseException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                throw e;
            } catch (JsonMappingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                throw e;
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                throw e;
            }
            return mapList;
        }
    
        /**
         * @Author AlphaJunS
         * @Date 19:09 2020/3/27
         * @Description map转json
         * @param map
         * @return java.lang.String
         */
        public static String mapToJson(Map<String,Object> map) throws Exception{
            ObjectMapper objectMapper = new ObjectMapper();
            String jsonString = objectMapper.writeValueAsString(map);
            return jsonString;
        }
    
        /**
         * @Author AlphaJunS
         * @Date 19:10 2020/3/27
         * @Description 对象转json
         * @param object
         * @return java.lang.String
         */
        public static String objectToJson(Object object) throws Exception{
            ObjectMapper objectMapper = new ObjectMapper();
            String jsonList;
            try {
                jsonList = objectMapper.writeValueAsString(object);
            } catch (JsonParseException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                throw e;
            } catch (JsonMappingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                throw e;
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                throw e;
            }
            return jsonList;
        }
    
        /**
         * @Author AlphaJunS
         * @Date 20:52 2020/3/27
         * @Description List>转json
         * @param cardInfoList
         * @return java.lang.String
         */
        public static String mapListToJson(List<Map<String, Object>> cardInfoList) throws Exception{
            ObjectMapper objectMapper = new ObjectMapper();
            String jsonList;
            try {
                jsonList = objectMapper.writeValueAsString(cardInfoList);
            } catch (JsonParseException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                throw e;
            } catch (JsonMappingException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                throw e;
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
                throw e;
            }
            return jsonList;
        }
    
        /**
         * @Author AlphaJunS
         * @Date 20:57 2020/3/27
         * @Description 数组转json
         * @param args
         * @return java.lang.String
         */
        public static String arrayToJson(String[] args) throws Exception{
            // 先讲数组转化为map,然后map转json
            Map<String,String> map = new HashMap<String,String>();
            for(int i=0; i<args.length; i++){
                map.put(i+"", args[i]);
            }
            String json = JsonUtil.objectToJson(map);
            return json;
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    /**
     * 
     * Cookie 工具类
     *
     */
    public final class CookieUtils {
    
    	static final Logger logger = LoggerFactory.getLogger(CookieUtils.class);
    
    	/**
    	 * 得到Cookie的值, 不编码
    	 * 
    	 * @param request
    	 * @param cookieName
    	 * @return
    	 */
    	public static String getCookieValue(HttpServletRequest request, String cookieName) {
    		return getCookieValue(request, cookieName, false);
    	}
    
    	/**
    	 * 得到Cookie的值,
    	 * 
    	 * @param request
    	 * @param cookieName
    	 * @return
    	 */
    	public static String getCookieValue(HttpServletRequest request, String cookieName, boolean isDecoder) {
    		Cookie[] cookieList = request.getCookies();
    		if (cookieList == null || cookieName == null){
    			return null;			
    		}
    		String retValue = null;
    		try {
    			for (int i = 0; i < cookieList.length; i++) {
    				if (cookieList[i].getName().equals(cookieName)) {
    					if (isDecoder) {
    						retValue = URLDecoder.decode(cookieList[i].getValue(), "UTF-8");
    					} else {
    						retValue = cookieList[i].getValue();
    					}
    					break;
    				}
    			}
    		} catch (UnsupportedEncodingException e) {
    			logger.error("Cookie Decode Error.", e);
    		}
    		return retValue;
    	}
    
    	/**
    	 * 得到Cookie的值,
    	 * 
    	 * @param request
    	 * @param cookieName
    	 * @return
    	 */
    	public static String getCookieValue(HttpServletRequest request, String cookieName, String encodeString) {
    		Cookie[] cookieList = request.getCookies();
    		if (cookieList == null || cookieName == null){
    			return null;			
    		}
    		String retValue = null;
    		try {
    			for (int i = 0; i < cookieList.length; i++) {
    				if (cookieList[i].getName().equals(cookieName)) {
    					retValue = URLDecoder.decode(cookieList[i].getValue(), encodeString);
    					break;
    				}
    			}
    		} catch (UnsupportedEncodingException e) {
    			logger.error("Cookie Decode Error.", e);
    		}
    		return retValue;
    	}
    
    	/**
    	 * 生成cookie,并指定编码
    	 * @param request 请求
    	 * @param response 响应
    	 * @param cookieName name
    	 * @param cookieValue value
    	 * @param encodeString 编码
    	 */
    	public static final void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, String encodeString) {
    		setCookie(request,response,cookieName,cookieValue,null,encodeString, null);
    	}
    
    	/**
    	 * 生成cookie,并指定生存时间
    	 * @param request 请求
    	 * @param response 响应
    	 * @param cookieName name
    	 * @param cookieValue value
    	 * @param cookieMaxAge 生存时间
    	 */
    	public static final void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, Integer cookieMaxAge) {
    		setCookie(request,response,cookieName,cookieValue,cookieMaxAge,null, null);
    	}
    
    	/**
    	 * 设置cookie,不指定httpOnly属性
    	 */
    	public static final void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, Integer cookieMaxAge, String encodeString) {
    		setCookie(request,response,cookieName,cookieValue,cookieMaxAge,encodeString, null);
    	}
    
    	/**
    	 * 设置Cookie的值,并使其在指定时间内生效
    	 * 
    	 * @param cookieMaxAge
    	 *            cookie生效的最大秒数
    	 */
    	public static final void setCookie(HttpServletRequest request, HttpServletResponse response, String cookieName, String cookieValue, Integer cookieMaxAge, String encodeString, Boolean httpOnly) {
    		try {
    			if(StringUtils.isBlank(encodeString)) {
    				encodeString = "utf-8";
    			}
    
    			if (cookieValue == null) {
    				cookieValue = "";
    			} else {
    				cookieValue = URLEncoder.encode(cookieValue, encodeString);
    			}
    			Cookie cookie = new Cookie(cookieName, cookieValue);
    			if (cookieMaxAge != null && cookieMaxAge > 0)
    				cookie.setMaxAge(cookieMaxAge);
    			if (null != request)// 设置域名的cookie
    				cookie.setDomain(getDomainName(request));
    			cookie.setPath("/");
    
    			if(httpOnly != null) {
    				cookie.setHttpOnly(httpOnly);
    			}
    			response.addCookie(cookie);
    		} catch (Exception e) {
    			logger.error("Cookie Encode Error.", e);
    		}
    	}
    
    	/**
    	 * 得到cookie的域名
    	 */
    	private static final String getDomainName(HttpServletRequest request) {
    		String domainName = null;
    
    		String serverName = request.getRequestURL().toString();
    		if (serverName == null || serverName.equals("")) {
    			domainName = "";
    		} else {
    			serverName = serverName.toLowerCase();
    			serverName = serverName.substring(7);
    			final int end = serverName.indexOf("/");
    			serverName = serverName.substring(0, end);
    			final String[] domains = serverName.split("\\.");
    			int len = domains.length;
    			if (len > 3) {
    				// www.xxx.com.cn
    				domainName = domains[len - 3] + "." + domains[len - 2] + "." + domains[len - 1];
    			} else if (len <= 3 && len > 1) {
    				// xxx.com or xxx.cn
    				domainName = domains[len - 2] + "." + domains[len - 1];
    			} else {
    				domainName = serverName;
    			}
    		}
    
    		if (domainName != null && domainName.indexOf(":") > 0) {
    			String[] ary = domainName.split("\\:");
    			domainName = ary[0];
    		}
    		return domainName;
    	}
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175

    html:

    DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Titletitle>
        <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js">script>
    head>
    <body>
    
        <div id="form_data">
            <input type="text" name="name" id="name"><br>
            <input type="password" name="password" id="password"><br>
            <button id="sub_ajax">login inbutton>
        div>
    
        <div id="res">div>
    
        <button id="getData">获取数据button>
        <hr>
        <table border="1" id="dataTable">
            <tr>
                <td>idtd>
                <td>nametd>
            tr>
        table>
    
        <script>
            $("#sub_ajax").click(function () {
                $.ajax({
                    url:'/user/login',
                    type:'post',
                    dataType:'json',
                    data:{name:$("#name").val()},
                    success:function (res) {
                        $("#res").html(res.token);
                    },
                    error:function (res) {
                        console.log(res);
                    }
                })
            });
    
            $("#getData").click(function () {
                $.ajax({
                    url:'/user/list',
                    type:'get',
                    dataType:'json',
                    data:{},
                    success:function (res) {
                        var tb = '\n' +
                            '            id\n' +
                            '            name\n' +
                            '        ';
                        for(var i = 0; i < res.length; i++){
                            var tr = '\n' +
                                '            '+res[i].id+'\n' +
                                '            '+res[i].name+'\n' +
                                '        ';
                            tb += tr;
                        }
                        $("#dataTable").html(tb);
                    },
                    error:function (res) {
                        console.log(res);
                    }
                })
            });
        script>
    
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    et’,
    dataType:‘json’,
    data:{},
    success:function (res) {
    var tb = ‘\n’ +
    ’ id\n’ +
    ’ name\n’ +
    ’ ‘;
    for(var i = 0; i < res.length; i++){
    var tr = ‘\n’ +
    ’ ’+res[i].id+‘\n’ +
    ’ ‘+res[i].name+’\n’ +
    ’ ';
    tb += tr;
    }
    $(“#dataTable”).html(tb);
    },
    error:function (res) {
    console.log(res);
    }
    })
    });

    ```
  • 相关阅读:
    css 将div固定在页面顶部不随页面滑动
    C++模板特化的两种形式:全特化和部分特化
    BUUCTF crypto做题记录(8)新手向
    vue3开发必备核心要点
    网络安全(黑客)-小白自学
    逍遥魔兽:如何在服务器上挂机器人?
    Springboot视图解析与模板引擎~
    计算机视觉(三):基于Scipy图像处理技术,图像模糊(灰色、彩色图像高斯模糊)、图像导数(sobel算子滤波)
    这一篇让你掌握 vue3.2 setup 语法糖
    JAVA计算机毕业设计校园社团管理平台演示录像2021Mybatis+源码+数据库+lw文档+系统+调试部署
  • 原文地址:https://blog.csdn.net/Linging_24/article/details/126077650