基于jetty httpservlet JWTtoken cookie实现一个api 的验证安全机制

先介绍HttpServletRequest 用户请求对象
1.用户请求对象包含:
 请求行  请求头   请求体

     // 获取请求的网址
    System.out.println(request.getRequestURL());
    // http://localhost:8080/sh-web-servlet02/demo08
    System.out.println(request.getRequestURI());
    // /sh-web-servlet02/demo08
    // 获取请求的类型(用浏览器直接请求都是get请求)
    System.out.println(request.getMethod());// GET
    // 获取请求路径 (相对路径)
    System.out.println(request.getContextPath());// /sh-web-servlet02

    // 获取请求中携带的参数
    // 参数是 提交表单时 表单的name属性
    String username = request.getParameter("username");
    String password = request.getParameter("password");
    System.out.println(username + "..." + password);

    // 判断浏览器
    // 可以通过请求头中的信息获取用户使用的浏览器
    String header = request.getHeader("User-Agent");
    System.out.println(header);
    if (header.toLowerCase().contains("firefox")) {
        System.out.println("用的是火狐");
    }else if (header.toLowerCase().contains("chrome")) {
        System.out.println("用的是谷歌");
    }else {
        System.out.println("其他浏览器");
    }
}


请求转发 请求重定向 请求包含
2. jetty实现api接口并生成token和添加cookie

jetty时比较轻量级的开源的服务器容器,相对于tomcat来说更轻量。便于用户进行第二次开发。具体的功能多在hondler中实现。多用于嵌入式行业中。

 private void startJettyServer() {
        String webPort = System.getenv("PORT");
        if (webPort == null || webPort.isEmpty()) {
            webPort = System.getProperty("PORT");
        }
        if (webPort == null || webPort.isEmpty()) {
            webPort = "8080";
        }

        server = new Server(Integer.valueOf(webPort));
        WebAppContext root = new WebAppContext();
        ServletHolder loginServletHolder = new ServletHolder(new LoginServlet());
        root.addServlet(loginServletHolder, "/login/*");
}

实现LoginServlet类 

package org.eclipse.leshan.standalone.servlet;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

import org.eclipse.leshan.standalone.utils.JwtUtil;

import net.sf.json.JSONObject;


public class LoginServlet extends HttpServlet
{

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String username = request.getParameter("username");
        System.out.print("username:"+username);
        String token = JwtUtil.generateToken(username, 60*60*60);
        response.setContentType("application/json");
        JSONObject repResult = new JSONObject();
        JSONObject repObj = new JSONObject();
        repResult.put("status", "success");
        repResult.put("token", token);
        repObj.put("result", repResult);
        response.setStatus(HttpServletResponse.SC_OK);
        PrintWriter toClient = response.getWriter();
        toClient.println(repObj);
    }
}

实现jwttoken工具类:

package org.eclipse.leshan.standalone.utils;

import com.auth0.jwt.internal.org.apache.commons.codec.binary.Base64;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.eclipse.leshan.standalone.servlet.CommonServlet;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;

public class JwtUtil {
    private static final String signingKey = "signingKey";

    public static String generateToken( String subject, long timeToAlive) {
        SecretKey key = generalKey();
        long nowMillis = System.currentTimeMillis();
        Date now = new Date(nowMillis);
        JwtBuilder builder = Jwts.builder()
            .setSubject(subject)
            .setIssuedAt(now)
            .signWith(SignatureAlgorithm.HS256, key);
        if (timeToAlive > 0) {
            Date exp = new Date(nowMillis + timeToAlive);
            builder.setExpiration(exp);
        }
        return builder.compact();
    }

    public static String getSubject(HttpServletRequest req, String jwtTokenCookieName){
        SecretKey key = generalKey();
        String token = req.getHeader(CommonServlet.headerName);
        if(token == null) return null;
        return Jwts.parser().setSigningKey(key).parseClaimsJws(jwtTokenCookieName).getBody().getSubject();
    }

    static private SecretKey generalKey() {
        byte[] encodedKey = Base64.decodeBase64(signingKey);

        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");

        return key;
    }
}

3.实现一个commonSevlet的类,当api访问时先验证token的值如果token有效然后调用相应的do函数

public class CommonServlet extends HttpServlet
{
    public static final String headerName = "Authorization";
    private static final Logger LOG = LoggerFactory.getLogger(CommonServlet.class);

    private boolean isValid(HttpServletRequest httpServletRequest, String token){
        try{
            String username = JwtUtil.getSubject(httpServletRequest, token);
            LOG.info("jwtusername",username);
            if(username == null){
                return false;
            }
        }catch(Exception e){
            LOG.info("jwtError", e);
            return false;
        }

        return true;
    }

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        String token = req.getHeader(headerName);
        resp.setHeader("Access-Control-Allow-Origin", "*");
        if(isValid(req, token)){
            super.service(req, resp);
        }else{
            JSONObject repResult = new JSONObject();
            JSONObject repObj = new JSONObject();
            repResult.put("status", "error");
            repResult.put("content", "illegal user");
            repObj.put("result", repResult);
            resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
            PrintWriter toClient = resp.getWriter();
            toClient.println(repObj);
        }
    }

}


4.cookie(客户端技术)
  cookie是保存在浏览器中的缓存数据
  当发起一个请求 请求一个servlet
  进行逻辑处理(添加一个商品进购物车)
  处理完成后 给客户端(浏览器)一个响应
  响应中携带着记录了购买的什么商品的 cookie
  让浏览器保存起来 可以是保存在内存当中(结束会话 cookie被清除) 
  也可以保存在硬盘当中(结束会话 依然存在 就是个文件)
  当浏览器再一次请求购物车的时候
  会携带着之前保存的 cookie 去访问

  每个网站可以保存20个cookie 整个浏览器可以保存300个
  注意:第一次访问服务器的时候 是不会携带着cookie去访问的
  因为cookie还没有产生 只有当第一次请求后的响应中可以把cookie写回到浏览器中 利用cookie 显示上次登录的时间
 

package leshan.standalone.utils;

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

public class CookieUtil {
    public static void create(HttpServletResponse httpServletResponse, String name, String value, Boolean secure, Integer maxAge, String domain) {
        Cookie cookie = new Cookie(name, value);
        cookie.setSecure(secure);
        cookie.setHttpOnly(true);
        cookie.setMaxAge(maxAge);
        cookie.setDomain(domain);
        cookie.setPath("/");
        httpServletResponse.addCookie(cookie);
    }

    public static void clear(HttpServletResponse httpServletResponse, String name) {
        Cookie cookie = new Cookie(name, null);
        cookie.setPath("/");
        cookie.setHttpOnly(true);
        cookie.setMaxAge(0);
        httpServletResponse.addCookie(cookie);
    }

    public static String getValue(HttpServletRequest httpServletRequest, String name) {
        Cookie[] cookies =  httpServletRequest.getCookies();
        if (cookies != null) {
            // 遍历数组
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals(name)) {
                    // 取出cookie的值
                    String value = cookie.getValue();
                    // 字符串转long
                    return value;

                }
            }
        }
        return null;
    }
}

这样就实现了一个当用户第一次登录时,后台生成token后设置到前台的cookie中,并设置过期时间。然后当用户通过api再次访问的时候就可以验证cookie中的token。保证用户信息的安全性。

猜你喜欢

转载自blog.csdn.net/margin_0px/article/details/83860134
今日推荐