利用jwt生成token,用于http请求身份验证

  前段时间在做移动端接口过程中,考虑到安全性,所有移动端发送请求(除了登录请求)过程中进行token有效验证。

   1.利用jwt生成token

   a.导入jwt相关包

  

        <!-- jwt -->
        <dependency>
            <groupId>com.nimbusds</groupId>
            <artifactId>nimbus-jose-jwt</artifactId>
            <version>4.23</version>
        </dependency>            

 

   b.编写生成token的工具类TokenUtils

  

public class TokenUtils {

    private static final byte[] secret = "geiwodiangasfdjsikolkjikolkijswe".getBytes();


    //生成一个token
    public static String creatToken(String uid) throws JOSEException {

        Map<String,Object> payloadMap = new HashMap<>();
        payloadMap.put("uid", uid);
        //生成时间
        payloadMap.put("sta", new Date().getTime());
        //过期时间
        payloadMap.put("exp", new Date().getTime()+1000*60*60*24); //24小时token失效
        
        //先建立一个头部Header
        JWSHeader jwsHeader = new JWSHeader(JWSAlgorithm.HS256);

        //建立一个载荷Payload
        Payload payload = new Payload(new JSONObject(payloadMap));

        //将头部和载荷结合在一起
        JWSObject jwsObject = new JWSObject(jwsHeader, payload);

        //建立一个密匙

        JWSSigner jwsSigner = new MACSigner(secret);

        //签名
        jwsObject.sign(jwsSigner);

        //生成token
        return jwsObject.serialize();
    }
    

    public static Map<String,Object> valid(String token) throws JOSEException, ParseException {

        JWSObject jwsObject = JWSObject.parse(token);

        //获取到载荷
        Payload payload=jwsObject.getPayload();

        //建立一个解锁密匙
        JWSVerifier jwsVerifier = new MACVerifier(secret);

        Map<String, Object> resultMap = new HashMap<>();
        //判断token
        if (jwsObject.verify(jwsVerifier)) {
            resultMap.put("Result", 0);
            //载荷的数据解析成json对象。
            JSONObject jsonObject = payload.toJSONObject();
            resultMap.put("data", jsonObject);

            //判断token是否过期
            if (jsonObject.containsKey("exp")) {
                Long expTime = Long.valueOf(jsonObject.get("exp").toString());
                Long nowTime = new Date().getTime();
                //判断是否过期
                if (nowTime > expTime) {
                    //已经过期
                    resultMap.clear();
                    resultMap.put("Result", 2);
                }
            }
        }else {
            resultMap.put("Result", 1);
        }
        return resultMap;

    }
}

  

    2.对于移动端所有请求进行过滤

    a.在web.xml中配置相关过滤器(对所有请求含有/app开头的进行拦截,除了/app/login)

    

   <filter>
        <filter-name>AppRequestFilter</filter-name>
        <filter-class>com.demo.common.filter.AppRequestFilter</filter-class>
        <init-param>
            <param-name>excludedRequests</param-name>
            <param-value>/app/login</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>AppRequestFilter</filter-name>
        <url-pattern>/app/*</url-pattern>
    </filter-mapping>

    b.编写AppRequestFilter类

    

public class AppRequestFilter implements Filter{
    
    private String excludedRequests;
    private String[] excludedRequestArr;
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        excludedRequests = filterConfig.getInitParameter("excludedRequests");
        if(excludedRequests != null && excludedRequests.length() > 0){
            excludedRequestArr = excludedRequests.split(",");
        }
        return;
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        
        boolean isExcludedRequest = false;
        for (String requestStr : excludedRequestArr) {
            if (((HttpServletRequest) request).getServletPath().startsWith(requestStr)) {
                isExcludedRequest = true;
                break;
            }
        }
        if(isExcludedRequest){
            chain.doFilter(request, response);
        }else{
            String token = req.getHeader("app_token");
            if(StringUtil.isEmpty(token)){
                responseError(res, "token为空!");
                return;
            }else{
                Map<String, Object> validMap;
                try {
                    validMap = TokenUtils.valid(token);
                    int i = (int) validMap.get("Result");
                    if (i == 0) {
                        chain.doFilter(request, response);
                    } else if (i == 2) {
                        responseError(res, "token已经过期!");
                        return;
                    } else if(i == 1) {
                        responseError(res, "token无效!");
                        return;
                    }
                } catch (JOSEException e) {
                    e.printStackTrace();
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }
            
        }
    }
    
    @SuppressWarnings("deprecation")
    private void responseError(HttpServletResponse res, String errorMsg) throws IOException {
        res.setHeader("content-type", "application/json;charset=UTF-8");
        OutputStream outputStream = res.getOutputStream();
        JsonResult msg = new JsonResult(false, errorMsg);
        IOUtils.write(JSONUtil.toJsonPrettyStr(msg), outputStream);
    }

    @Override
    public void destroy() {
        return;
    }
}

    3.测试类编写

    

@Controller
@RequestMapping(value = "/app")
public class AppLogin {

    @RequestMapping(value = "/login")
    @ResponseBody
    public String login(String loginCode, String password){
        String token = "";
        try {
            token = TokenUtils.creatToken(loginCode);
        } catch (JOSEException e) {
            e.printStackTrace();
        }
        return token;
    }
}
@Controller
@RequestMapping(value = "/app/user")
public class AppSysUserController {

    @RequestMapping(value = "/getLoginName")
    @ResponseBody
    public String getLoginName(){
        return "admin";
    }
}

    4.调用查看结果

    

 

    

 

 


posted @ 2018-09-27 15:46  其实我还是个孩子丶  阅读(902)  评论(0编辑  收藏  举报