Tlias 项目登录功能

Tlias 项目登录功能

登录校验

  • ;要对所有接口做校验 /emps/.. /depts/.. 每个方法内实现太冗余, 因此一般使用 统一拦截.

会话技术

  • 访问web 资源, 会话建立, 一方断开连接, 会话结束, 一次会话可以有多个请求
    • 可以理解为 一个会话就是一个浏览器, 关闭浏览器会关闭会话.
    • 会话跟踪: 识别请求是否来自同一个会话. 同一个会话可以共享数据.
      • cookie
      • session
      • 令牌技术

  • 存储在客户端(浏览器);
  • 跨域: 前端一个服务器, 后端一个服务器, 跨域cookie不能传递.

session

  • 存储在服务端

令牌

  • 缺点: 自己实现

  • 令牌伪造? 有签名防止伪造

jwt

  • json web token
@Test  
public void testGenJwt(){  
    Map<String, Object> claims = new HashMap<>();  
    claims.put("id",1);  
    claims.put("name","Tom");  
    String jwt = Jwts.builder()  
            .signWith(Jwts.SIG.HS256.key().build())  
            .claims(claims)  
            .expiration(new Date(System.currentTimeMillis() + 3600 * 1000))  
            .compact();  
    log.info(jwt);  
}


// 生成
@Test  
public void testGenJwt(){  
    Map<String, Object> claims = new HashMap<>();  
    claims.put("id",1);  
    claims.put("name","Tom");  

    //  hs256 秘钥 32 字节或更长  
    String secretString = "itheimaaitheimaaitheimaaitheimaa";  
    SecretKey key = Keys.hmacShaKeyFor(secretString.getBytes());  
    SecretKey key1 = Jwts.SIG.HS256.key().random(new SecureRandom(secretString.getBytes())).build();  

    String jwt = Jwts.builder()  
            .signWith(key1)  //.signWith(key, Jwts.SIG.HS256)
            .claims(claims)  
            .expiration(new Date(System.currentTimeMillis() + 3600 * 1000))  
            .compact();  
    log.info(jwt);  
}


// 验证
@Test  
public void testJwtParse(){  
    String s = "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiVG9tIiwiaWQiOjEsImV4cCI6MTczNTI5ODIwN30.wSQfN3enbWTxkoPxzC93DMdspWgePCN8ZDyoaLIwzm0";  
    String s1 = "eyJhbGciOiJIUzI1NiJ9.eyJuYW1lIjoiVG9tIiwiaWQiOjEsImV4cCI6MTczNTMwMzUyN30.EAtq-NKUXQ4ePmEthOCRyKImWYH1tISUOPRW8mI13Y8";  
    String secretString = "itheimaaitheimaaitheimaaitheimaa";  
    SecretKey key = Keys.hmacShaKeyFor(secretString.getBytes());  
    SecretKey key1 = Jwts.SIG.HS256.key().random(new SecureRandom(secretString.getBytes())).build();  
    Jws<Claims> claimsJws = Jwts.parser()  
            .verifyWith(key1)  //.verifyWith(key, Jwts.SIG.HS256)
            .build()  
            .parseSignedClaims(s1);  

    Map<String, Object> b = claimsJws.getPayload();  
    log.info(b.toString());  
}


// https://jwt.io/

java
@PostMapping("/login")  
public Result login(@RequestBody Emp emp){  
    log.info("员工登录{},{}",emp);  
    Emp empRet = empService.login(emp);  
    if(empRet == null){  
        return Result.error("用户名或密码错误");  
    }else{  
        Map<String ,Object> map = new HashMap<>();  
        map.put("id",empRet.getId());  
        map.put("name",empRet.getName());  
        map.put("username",empRet.getUsername());  
        String token = JwtUtils.getToken(map);// jwt 中包含员工登录的信息  
        return Result.success(token);  
    }  
}

Filter

  • 默认按类名排序
实现 @WebFilter


    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {  
        System.out.println("拦截器");  
        HttpServletRequest request = (HttpServletRequest) servletRequest;  
        HttpServletResponse response = (HttpServletResponse) servletResponse;  

        // 1. 获取请求url  
        String url = request.getRequestURI();  

        // 2. 有login 说明是登录请求, 放行  
        if(url.contains("login")){  
            filterChain.doFilter(servletRequest, servletResponse);  
            return;  
        }  

        // 3. 没有login , 查看token, 没有token 返回错误  
        String token = request.getHeader("token");  
        if(token == null||token.isEmpty()){  
//            Result.error("NOT_LOGIN");  
            // fastJson 转换  
            String notLogin = JSONObject.toJSONString(Result.error("NOT_LOGIN"));  
            response.getWriter().write(notLogin);  
            return;  
        }  
        // 4. 解析token,  错误 返回错误  
        try {  
            Claims claims = JwtUtils.parseToken(token);  
        } catch (Exception e) {  
            e.printStackTrace();  
            System.out.println("解析令牌失败");  
            String notLogin = JSONObject.toJSONString(Result.error("NOT_LOGIN"));  
            response.getWriter().write(notLogin);  
            return;  

        }  

        // 5. 放行  
        System.out.println("令牌合法, 放行");  
        filterChain.doFilter(servletRequest, servletResponse);  
    }

interceptor

路径

执行流程

实现 @Configuration
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {  
        System.out.println("preHandle .........");  
        // 1. 获取请求url  
        String url = request.getRequestURI();  

        // 2. 有login 说明是登录请求, 放行  
        if(url.contains("login")){  
            return true;  
        }  

        // 3. 没有login , 查看token, 没有token 返回错误  
        String token = request.getHeader("token");  
        if(token == null||token.isEmpty()){  
//            Result.error("NOT_LOGIN");  
            // fastJson 转换  
            String notLogin = JSONObject.toJSONString(Result.error("NOT_LOGIN"));  
            response.getWriter().write(notLogin);  
            return false;  
        }  
        // 4. 解析token,  错误 返回错误  
        try {  
            Claims claims = JwtUtils.parseToken(token);  
        } catch (Exception e) {  
            e.printStackTrace();  
            System.out.println("解析令牌失败");  
            String notLogin = JSONObject.toJSONString(Result.error("NOT_LOGIN"));  
            response.getWriter().write(notLogin);  
            return false;  

        }  

        // 5. 放行  
        System.out.println("令牌合法, 放行");  
        return true;  
    }

区别