系统登陆验证过程(验证token是否合理)

       现在我主要介绍一下,用户后台登陆系统之后,使用token来校验用户是否合法,使用户信息保持正确。相关代码我已放入下面,有需要的朋友即可尝试一下。

1.首先看到web.xml 

 <!--配置,解决请求乱码问题-->
    <filter>
        <filter-name>CharacterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>utf-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>CharacterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

    <!--自定义拦截器-->
    <filter>
        <filter-name>myAuthenticationFilter</filter-name>
        <filter-class>com.javaclimb.util.filter.MyWebFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>myAuthenticationFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

2.找到自定义拦截器的MyWebFilter3.

package com.javaclimb.util.filter;

import com.alibaba.druid.support.json.JSONUtils;
import com.javaclimb.util.Consts;
import com.nimbusds.jose.JOSEException;
import com.javaclimb.util.MapWrapperUtils;
import com.javaclimb.util.ReturnData;
import com.javaclimb.util.TextUtils;
import com.javaclimb.util.exception.CustomerException;
import com.javaclimb.util.jwt.JwtUtil;
import org.springframework.web.filter.GenericFilterBean;

import javax.servlet.FilterChain;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 *拦截
 */
public class MyWebFilter extends GenericFilterBean {
    public static final String FROM_MICRO = "micro";
    public static final String USER_TYPE_NORMAL = "userTypeNormal";

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) {
        HttpServletRequest req = ((HttpServletRequest) request);
        HttpServletResponse resp = ((HttpServletResponse) response);
        System.out.println(req.getRequestURL());

        List<String> urlIgnorelist = new ArrayList<>();
        urlIgnorelist.add("/resources/");
        urlIgnorelist.add("/upload/");
        urlIgnorelist.add("/requestLogin");
        urlIgnorelist.add("/user/getUserByCode");
        urlIgnorelist.add("/advertisement/getList");
        urlIgnorelist.add("/goods/getList");
        urlIgnorelist.add("/goodsType/getList");
        urlIgnorelist.add("/login");
        urlIgnorelist.add("/regist");
        urlIgnorelist.add("/logout");

        boolean isNeedDealwith = true;
        for (String path : urlIgnorelist) {
            if (req.getServletPath().contains(path)) {
                isNeedDealwith = false;
                break;
            }
        }
        try {
            //判断用户的请求来源
            String from = req.getHeader("from");
            if (TextUtils.isEmpty(from)) {
                //web端
                if (isNeedDealwith) {
                    //判断当前用户是否登录
                    HttpSession session = req.getSession();
                    Object o = session.getAttribute(Consts.SYS_USER_INFO);
                    if (o == null) {
                        resp.sendRedirect(req.getContextPath() + "/login");
                    } else {
                        //重新设置,这样就会重新计算失效时间
                        session.setAttribute(Consts.SYS_USER_INFO, o);
                    }
                }
                filterChain.doFilter(req, resp);
            } else if (FROM_MICRO.equals(from)) {

                //移动端登录
                resp.setCharacterEncoding("utf-8");
                resp.setContentType("application/json; charset=utf-8");
                if (!isNeedDealwith) {
                    filterChain.doFilter(req, resp);
                    return;
                }
                String token = req.getHeader("token");
                if (TextUtils.isEmpty(token)) {
                    makeResponse(resp, ReturnData.fail("请携带token"));
                    return;
                }
                ReturnData returnData = JwtUtil.valid(token);
                if (returnData.getCode() != 200) {
                    makeResponse(resp, returnData);
                    return;
                }
                Long id = (Long) returnData.getData();
                if (id == null) {
                    makeResponse(resp, ReturnData.fail("token有误"));
                    return;
                }
                //利用原始的request对象创建自己扩展的request对象并添加自定义参数
                RequestParameterWrapper requestParameterWrapper = new RequestParameterWrapper(req);
                Map<String, Object> param = new HashMap<>();
                param.put(MapWrapperUtils.KEY_USER_ID, id);
                requestParameterWrapper.addParameters(param);
                filterChain.doFilter(requestParameterWrapper, resp);
            } else {
                makeResponse(resp, ReturnData.fail("from参数有误"));
            }
        } catch (JOSEException e) {
            makeResponse(resp, ReturnData.fail("token异常"));
        } catch (Exception e) {
            Throwable throwable = e.getCause();
            System.out.println(throwable.getCause());
            if (throwable instanceof CustomerException) {
                makeResponse(resp, ReturnData.fail(((CustomerException) throwable).getMsgDes()));
            } else {
                makeResponse(resp, ReturnData.fail(throwable.getCause() == null ? e.getMessage() : throwable.getCause().getMessage()));
            }
        }

    }

    private void makeResponse(HttpServletResponse resp, ReturnData returnData) {
        try {
            resp.getWriter().print(JSONUtils.toJSONString(returnData));
            resp.getWriter().close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3.使用 JwtUtil来判断token是否合法

import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jose.crypto.MACVerifier;
import com.javaclimb.util.MapWrapperUtils;
import com.javaclimb.util.ReturnData;
import com.javaclimb.util.exception.CustomerException;
import net.minidev.json.JSONObject;

import java.text.ParseException;
import java.util.Date;
import java.util.Map;


public class JwtUtil {
    /**
     * 1.创建一个32-byte的密匙
     */

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


    //生成一个token
    public static String creatToken(Map<String, Object> payloadMap) {

        //3.先建立一个头部Header
        /**
         * JWSHeader参数:1.加密算法法则,2.类型,3.。。。。。。。
         * 一般只需要传入加密算法法则就可以。
         * 这里则采用HS256
         *
         * JWSAlgorithm类里面有所有的加密算法法则,直接调用。
         */
        JWSHeader jwsHeader = new JWSHeader(JWSAlgorithm.HS256);

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

        //将头部和载荷结合在一起
        JWSObject jwsObject = new JWSObject(jwsHeader, payload);
        try {
            //建立一个密匙
            JWSSigner jwsSigner = new MACSigner(secret);

            //签名
            jwsObject.sign(jwsSigner);
        } catch (JOSEException e) {
            throw new CustomerException("toke生成失败");
        }
        //生成token
        return jwsObject.serialize();
    }

    //解析一个token

    public static ReturnData valid(String token) throws ParseException, JOSEException {
        ReturnData returnData = null;
//        解析token

        JWSObject jwsObject = JWSObject.parse(token);

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

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

        //判断token
        if (jwsObject.verify(jwsVerifier)) {
            //载荷的数据解析成json对象。
            JSONObject jsonObject = payload.toJSONObject();
            returnData = ReturnData.success(jsonObject.get(MapWrapperUtils.KEY_USER_ID));
            //判断token是否过期
            if (jsonObject.containsKey("exp")) {
                Long expTime = Long.valueOf(jsonObject.get("exp").toString());
                Long nowTime = new Date().getTime();
                //判断是否过期
                if (nowTime > expTime) {
                    //已经过期
                    returnData = ReturnData.fail("登录过期");
                }
            }
        } else {
            returnData = ReturnData.fail("token令牌是个假的");
        }
        return returnData;
    }
}

4.MapWrapperUtils相关代码

package com.javaclimb.util;

import java.util.HashMap;

public class MapWrapperUtils extends HashMap<String, Object> {
    public static String KEY_USER_ID = "userId";

    @Override
    public MapWrapperUtils put(String key, Object value) {
        super.put(key, value);
        return this;
    }

    public static MapWrapperUtils builder(String key, Object value) {
        MapWrapperUtils wrapperUtils = new MapWrapperUtils();
        wrapperUtils.put(key, value);
        return wrapperUtils;
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Redis 是一种开源的内存数据存储系统,可用作数据库、缓存和消息中间件。在某些应用场景中,你可能需要使用 Redis 来验证 token,例如在身份认证和授权流程中。 具体来说,你可以将 token 作为 Redis 键存储在 Redis 中,并将相关的用户信息或其他相关数据作为值存储。当你需要验证 token 时,可以使用 Redis 的 `GET` 命令来获取该 token 对应的值。如果返回的值不为空,则说明该 token 是有效的;如果返回的值为空,则说明该 token 无效或已过期。 例如,假设你已将以下数据存储在 Redis 中: ``` Key Value "token:abcdefg" {"userId": 123, "expiresAt": 1623478213} ``` 你可以使用以下命令来验证 token: ``` GET "token:abcdefg" ``` 如果返回的值为 `{"userId": 123, "expiresAt": 1623478213}`,则说明该 token 有效。否则,该 token 无效。 需要注意的是,在使用 Redis 来存储 token 时,你还需要自己实现 token 的过期时间的检查。在上面的例子中,你可以使用 "expiresAt" 字段来检查 token 是否已过期。 ### 回答2: Reids是一个在使用Redis数据库时常用的功能。验证Token是一种常见的身份验证方法,用于确认用户身份和授权访问权限。 在实际应用中,验证Token过程主要包括以下几个步骤: 1. 客户端向服务器发送请求,携带Token作为身份凭证。 2. 服务器接收到请求后,首先需要从Redis中查询对应Token的相关信息。 3. 服务器通过Redis提供的功能进行Token的解析和验证,包括验证Token的有效性、过期时间等属性。 - 如果Token无效或已过期,服务器将拒绝该请求,并返回相应的错误信息。 - 如果Token有效且未过期,服务器可以进一步处理请求。 4. 在验证通过后,服务器可以根据Token中的信息(如用户ID、角色等)来决定用户是否有权执行该请求所需的操作。 5. 如果服务器需要更新、撤销Token等操作,也可以通过Redis实现。 Reids验证Token的优势在于其快速高效的性能,Redis具有内存数据库的特性,数据存取速度远高于传统磁盘存储的数据库系统。此外,Redis还提供了丰富的数据结构和功能,使得Token的处理和存储更加灵活和便捷。 总之,Reids验证Token是通过Redis数据库快速有效地对Token进行解析和验证,确保用户的身份和权限的一种方法。它能够提供安全可靠的身份验证机制,用于保护应用程序和用户的数据安全。 ### 回答3: Redis是一种内存数据库,可以用于存储和管理数据。在使用Redis验证token时,可以使用Redis的一些特定命令和功能来实现。 首先,可以使用Redis的SET命令将token作为键值对存储在Redis中。例如,可以将token作为键,用户ID或其他相关信息作为值存储起来。 然后,可以使用Redis的GET命令来获取特定token对应的值。通过将token作为键,就可以从Redis中获取对应的用户ID或其他相关信息。 此外,还可以使用Redis的EXPIRE命令来设置token的过期时间。可以根据实际需求设置合适的过期时间,使得token在一定时间后自动失效。 在验证token时,可以使用Redis的EXISTS命令来检查token是否存在。如果token存在于Redis中,则表示token有效;如果不存在,则表示token无效或已过期。 当然,在使用Redis进行token验证时,还可以结合其他验证机制,如JWT(JSON Web Token)等来增加安全性。可以在生成和验证token时,使用一些加密算法或签名方法来确保token的真实性和完整性。 总之,Redis可以作为一种快速、可靠的存储方式,用于验证token。通过合理地存储、获取、过期设置和检查token,可以有效地实现对用户身份的验证和控制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值