• SpringBoot学习- 4、整合JWT


    SpringBoot学习足迹

    1、Json web token(JWT)是为了网络应用环境间传递声明而执行的一种基于JSON的开发标准(RFC 7519),该token被设计为紧凑且安全的,特别适用于分布式站点的单点登陆(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。JWT听起来很复杂,其实原理很简单,比如我们可以自己生成一个guid字符串+key+附加信息加密作为token传递到客户端也能达到同样目的。

    2、pom.xml增加如下代码来添加JWT依赖包

    <!-- https://mvnrepository.com/artifact/com.auth0/java-jwt -->
    <dependency>
        <groupId>com.auth0</groupId>
        <artifactId>java-jwt</artifactId>
        <version>3.9.0</version>
    </dependency>

    3、IDEA2019.3版本中文乱码,设置UTF-8不起作用,修改字体如下

    以下几部分内容主要参考
    https://www.cnblogs.com/30go/p/10963924.html
    https://www.jianshu.com/p/9af8612f6aef

     4、在Utils文件夹下增加TokenUtil

    RefreshToken暂不使用

    package com.jgui.utils;
    
    import com.auth0.jwt.JWT;
    import com.auth0.jwt.algorithms.Algorithm;
    import com.auth0.jwt.interfaces.DecodedJWT;
    import com.auth0.jwt.interfaces.JWTVerifier;
    import com.jgui.domain.JUser;
    
    import java.util.Date;
    
    /**
     * @Author: zhaogaojian
     * @Description:
     * @Date: Created in 2020/1/722:13
     */
    public class TokenUtil {
        private static final long TOKEN_EXPIRE_TIME= 30*60*1000;//超时时间30分钟
        private static final long REFRESH_TOKEN_EXPIRE_TIME= 15*24*60*1000;//超时时间15天
        private static final String TOKEN_SECRET="jguiafadfiierpewirpew8908ewrq";//秘钥
        private static final String ISSUER="jgadmin";//签发人
        /**
         * 签名生成
         * @param user
         * @return
         */
        public static String sign(JUser user){
    
            String token = "";
            try {
                Date expiresAt = new Date(System.currentTimeMillis() + TOKEN_EXPIRE_TIME);
                Date now = new Date();
                token = JWT.create()
                        .withIssuer(ISSUER)
                        .withClaim("username", user.getUsername())
                        .withExpiresAt(expiresAt)
                        .withIssuedAt(now)
                        // 使用了HMAC256加密算法。
                        .sign(Algorithm.HMAC256(TOKEN_SECRET));
            } catch (Exception e){
                e.printStackTrace();
            }
            return token;
    
        }
        /**
         * 签名验证
         * @param token
         * @return
         */
        public static boolean verify(String token){
            try {
                JWTVerifier verifier = JWT.require(Algorithm.HMAC256(TOKEN_SECRET)).withIssuer("auth0").build();
                DecodedJWT jwt = verifier.verify(token);
                System.out.println("认证通过:");
                System.out.println("issuer: " + jwt.getIssuer());
                System.out.println("username: " + jwt.getClaim("username").asString());
                System.out.println("签发时间:" + jwt.getIssuedAt());
                System.out.println("过期时间:" + jwt.getExpiresAt());
                return true;
            } catch (Exception e){
                return false;
            }
    
        }
        /**
         * 从token获取username
         */
        public static String getUsername(String token){
            try{
                return JWT.decode(token).getClaim("username").asString();
            }catch(Exception ex){
                ex.printStackTrace();
            }
            return "";
        }
    }
    package com.jgui.utils;
    
    import java.util.UUID;
    
    /**
     * @Author: zhaogaojian
     * @Description:
     * @Date: Created in 2020/1/722:50
     */
    public class StringUtil {
        public static String GetUUIDString()
        {
           return UUID.randomUUID().toString();
        }
    
    }

    5、在Controller下增加LoginController

    package com.jgui.controller;
    
    import com.jgui.dao.JUserDao;
    import com.jgui.domain.JUser;
    import com.jgui.utils.StringUtil;
    import com.jgui.utils.TokenUtil;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.RequestParam;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.annotation.Resource;
    import java.util.Collection;
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Set;
    import java.util.concurrent.TimeUnit;
    
    /**
     * @Author: zhaogaojian
     * @Description:
     * @Date: Created in 2020/1/722:38
     */
    @RestController
    public class LoginController {
        @Resource
        private JUserDao userDao;
        @GetMapping("/login")
        public Map<String,Object> login(@RequestParam String username, @RequestParam String password) {
    
            if("zhangsan".equals(username) && "123".equals(password)){
                JUser user=new JUser();
                user.setUsername("zhangsan");
                user.setRealname("张三");
                Map<String,Object> map = new HashMap<>();
                //生成token
                String token = TokenUtil.sign(user);
                String refreshToken = StringUtil.GetUUIDString();
                if(token != ""){
                    map.put("code", "10000");
                    map.put("message", "认证成功");
                    map.put("token", token);
                    map.put("refreshtoken", refreshToken);
                    return map;
                }
            }
            Map<String,Object> map = new HashMap<>();
            map.put("code", "10001");
            map.put("message", "认证失败");
            map.put("token", "");
            map.put("refreshtoken", "");
            return map;
        }
    }

    6、在Interceptor目录下增加TokenInterceptor

    package com.jgui.interceptor;
    import com.jgui.utils.TokenUtil;
    import net.minidev.json.JSONObject;
    import org.springframework.stereotype.Component;
    import org.springframework.web.servlet.HandlerInterceptor;
    /**
     * @Author: zhaogaojian
     * @Description:
     * @Date: Created in 2020/1/723:12
     */
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.PrintWriter;
    @Component
    public class TokenInterceptor implements HandlerInterceptor {
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response,Object handler)throws Exception{
    
            if(request.getMethod().equals("OPTIONS")){
                response.setStatus(HttpServletResponse.SC_OK);
                return true;
            }
            response.setCharacterEncoding("utf-8");
            String token = request.getHeader("token");
            if(token != null){
                boolean result = TokenUtil.verify(token);
                if(result){
                    System.out.println("通过拦截器");
                    return true;
                }
            }
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json; charset=utf-8");
            PrintWriter out = null;
            try{
                JSONObject json = new JSONObject();
                json.put("success","false");
                json.put("msg","认证失败,未通过拦截器");
                json.put("code","10003");
                response.getWriter().append(json.toJSONString());
                System.out.println("认证失败,未通过拦截器");
            }catch (Exception e){
                e.printStackTrace();
                response.sendError(500);
                return false;
            }
            return false;
    
        }
    
    }

    7、在config下增加InterceptorConfig

    package com.jgui.config;
    
    /**
     * @Author: zhaogaojian
     * @Description:
     * @Date: Created in 2020/1/723:15
     */
    import com.jgui.interceptor.TokenInterceptor;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    import java.util.ArrayList;
    import java.util.List;
    /**
     * 拦截器配置
     */
    @Configuration
    public class InterceptorConfig implements WebMvcConfigurer {
        private TokenInterceptor tokenInterceptor;
        //构造方法
        public InterceptorConfig(TokenInterceptor tokenInterceptor){
            this.tokenInterceptor = tokenInterceptor;
        }
        @Override
        public void addInterceptors(InterceptorRegistry registry){
            List<String> excludePath = new ArrayList<>();
            excludePath.add("/login"); //登录
    
            registry.addInterceptor(tokenInterceptor)
                    .addPathPatterns("/**")
                    .excludePathPatterns(excludePath);
            WebMvcConfigurer.super.addInterceptors(registry);
        }
    }

    8、运行项目

    可以发现之前的http://localhost:8080/Hello

    访问时会因为拦截器而导致无法访问

    login接口因为被排除在拦截器外可以访问

     

     以上内容主要参考
    https://www.cnblogs.com/30go/p/10963924.html
    https://www.jianshu.com/p/9af8612f6aef

    截止目前项目结构如下

    上一节:SpringBoot学习- 3、整合MyBatis

  • 相关阅读:
    第四周技术博客发表 线性表
    《我是一只IT小小鸟》读后感
    java9最新发布
    MD5进行解密操作
    MD5进行加密操作
    定时器的编写
    mybatis查询修改同时操作
    java8的版本对组合式异步编程
    linux中安装gcc
    linux不能上网问题
  • 原文地址:https://www.cnblogs.com/zhaogaojian/p/12164349.html
Copyright © 2020-2023  润新知