精华内容
下载资源
问答
  • 登录成功后,使用用户id构造生成一个token并保存到redis中,同时也保存用户id到session中生成token的代码如下:@Overridepublic String createToken(String phone,String appId) throwsException {long loginTime =...

    登录成功后,使用用户id构造生成一个token并保存到redis中,同时也保存用户id到session中

    生成token的代码如下:

    @Overridepublic String createToken(String phone,String appId) throwsException {long loginTime =DateUtil.getNowTimeStampTime().getTime();

    String str= String.valueOf(phone) + CommonConstant.COMMA_CHARACTER+appId+ CommonConstant.COMMA_CHARACTER+String.valueOf(loginTime);byte[] cipherData = null;

    String result= null;

    cipherData= RSAEncrypt.encrypt(Rsa2Manager.getPublicKeyGmall(), str.getBytes("UTF-8"));//RSA加密

    result=Base64.encode(cipherData);//加密returnresult;

    }

    checkToken,获取当前session,有效则已登录,无效则获取当前的token,解密token,再去查询redis中的token是否有效,有效则再次对session赋值,还原登录状态

    @Override

    public boolean isLogin(HttpSession session) throws Exception {

    boolean islogin = false;

    String appId = (String) session.getAttribute(UserConstant.LOGIN_APP_ID);

    String userId = (String) session.getAttribute(UserConstant.USER_SESSION_KEY);

    if (StringUtils.isNotBlank(appId) && StringUtils.isNotBlank(userId)) {

    islogin = true;

    } else {

    String phone ="";

    String appid ="";

    HttpServletRequest request = getCurrentThreadRequest();

    String currentToken = request.getHeader(CommonConstant.REQUEST_HEADER_TOKEN_NAME);

    if(StringUtils.isNotBlank(currentToken)){

    byte[] res = null;

    res = RSAEncrypt.decrypt(Rsa2Manager.getPrivateKeyGmall(), Base64.decode(currentToken));

    String restr = new String(res);

    String[] str = restr.split(",");

    phone = str[0];

    appid = str[1];

    String redisKey = CommonConstant.LOGIN_TOKEN.concat(phone);

    String token = RedisUtil.getRedisString(redisKey);

    if (StringUtils.isNotBlank(token)) {

    request.getSession().setAttribute(UserConstant.USER_SESSION_KEY, phone);

    request.getSession().setAttribute(UserConstant.LOGIN_APP_ID, appid);

    islogin = true;

    }else{

    islogin = false;

    }

    }

    }

    return islogin;

    }

    展开全文
  • 主要介绍了php表单加入Token防止重复提交的方法,结合实例形式分析了Token防止重复提交的原理与使用技巧,需要的朋友可以参考下
  • DuplicateSubmitToken package jyuxuan.openpose.config; import java.lang.... * 防止表单重复提交注解 */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) @Documented public @interfa...

    DuplicateSubmitToken

    package jyuxuan.openpose.config;
    
    import java.lang.annotation.*;
    
    /**
     * 防止表单重复提交注解
     */
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.METHOD)
    @Documented
    public @interface DuplicateSubmitToken {
        // 一次请求完成之前防止重复提交
        public static final int REQUEST = 1;
    
        // 一次会话中防止重复提交
        public static final int SESSION = 2;
    
        // 保存重复提交标记 默认为需要保存
        boolean save() default true;
    
        // 防止重复提交类型,默认:一次请求完成之前防止重复提交
        int type() default REQUEST;
    }
    

    DuplicateSubmitException

    package jyuxuan.openpose.config;
    
    /**
     * 自定义异常
     */
    public class DuplicateSubmitException extends Exception {
    
        public DuplicateSubmitException(String msg){
            super(msg);
        }
    }
    

    TextConstants

    package jyuxuan.openpose.config;
    
    public class TextConstants {
        public static final String REQUEST_REPEAT = "========this is a duplicate submit exception=====";
    }
    

    DuplicateSubmitAspect

    package jyuxuan.openpose.config;
    
    import lombok.extern.slf4j.Slf4j;
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.*;
    import org.springframework.stereotype.Component;
    import org.springframework.web.context.request.RequestContextHolder;
    import org.springframework.web.context.request.ServletRequestAttributes;
    
    import javax.servlet.http.HttpServletRequest;
    import java.util.UUID;
    
    /**
     * 防止表单重复提交拦截器
     */
    @Aspect
    @Component
    @Slf4j
    public class DuplicateSubmitAspect {
        public static final String DUPLICATE_TOKEN_KEY = "duplicate_token_key";
    
        @Pointcut("execution(public * jyuxuan.openpose.controller..*(..))")
    
        public void webLog() {
        }
    
        @Before("webLog() && @annotation(token)")
        public void before(final JoinPoint joinPoint, DuplicateSubmitToken token) throws DuplicateSubmitException {
            if (token != null) {
                ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                HttpServletRequest request = attributes.getRequest();
    
                boolean isSaveSession = token.save();
                if (isSaveSession) {
                    String key = getDuplicateTokenKey(joinPoint);
                    Object t = request.getSession().getAttribute(key);
                    if (null == t) {
                        String uuid = UUID.randomUUID().toString();
                        request.getSession().setAttribute(key.toString(), uuid);
                        log.info("token-key=" + key);
                        log.info("token-value=" + uuid.toString());
                    } else {
                        throw new DuplicateSubmitException(TextConstants.REQUEST_REPEAT);
                    }
                }
    
            }
        }
    
        /**
         * 获取重复提交key
         * @param joinPoint
         * @return
         */
        public String getDuplicateTokenKey(JoinPoint joinPoint) {
            String methodName = joinPoint.getSignature().getName();
            StringBuilder key = new StringBuilder(DUPLICATE_TOKEN_KEY);
            key.append(",").append(methodName);
            return key.toString();
        }
    
        @AfterReturning("webLog() && @annotation(token)")
        public void doAfterReturning(JoinPoint joinPoint, DuplicateSubmitToken token) {
            // 处理完请求,返回内容
            log.info("出方法:");
            if (token != null) {
                ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                HttpServletRequest request = attributes.getRequest();
                boolean isSaveSession = token.save();
                if (isSaveSession) {
                    String key = getDuplicateTokenKey(joinPoint);
                    Object t = request.getSession().getAttribute(key);
                    if (null != t && token.type() == DuplicateSubmitToken.REQUEST) {
                        request.getSession(false).removeAttribute(key);
                    }
                }
            }
        }
    
        /**
         * 异常
         * @param joinPoint
         * @param e
         * @param token
         */
        @AfterThrowing(pointcut = "webLog()&& @annotation(token)", throwing = "e")
        public void doAfterThrowing(JoinPoint joinPoint, Throwable e, DuplicateSubmitToken token) {
            if (null != token
                    && e instanceof DuplicateSubmitException == false) {
                //处理处理重复提交本身之外的异常
                ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
                HttpServletRequest request = attributes.getRequest();
                boolean isSaveSession = token.save();
                //获得方法名称
                if (isSaveSession) {
                    String key = getDuplicateTokenKey(joinPoint);
                    Object t = request.getSession().getAttribute(key);
                    if (null != t) {
                        //方法执行完毕移除请求重复标记
                        request.getSession(false).removeAttribute(key);
                        log.info("异常情况--移除标记!");
                    }
                }
            }
        }
    }
    

    用户登录测试

    /**
     * 用户登录
     *
     * @param request
     * @param model
     * @return
     */
    @DuplicateSubmitToken(type = DuplicateSubmitToken.SESSION)
    @RequestMapping(value = "userLogin", method = RequestMethod.GET)
    public String userLogin_(HttpServletRequest request, Model model) {
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        String pwd = userService.userLogin(username);
        String msg;
        if (pwd == null || pwd.equals(""))
            msg = "该用户未注册";
        else if (pwd.equals(password))
            msg = "密码正确";
        else
            msg = "密码错误";
        return "index";
    }
    
    展开全文
  • token防止重复提交

    2020-09-14 10:00:33
    客户端请求放重复提交接口时要带上此token(一般是存放至请求头中),服务器端将检验此token,若token能够在session或redis中查找到,则删除此token并放行接口,若没能查找到,说明不是第一次提交,则拒绝放行 ...
    • 客户端获取页面时请求一次获取token的接口,服务器端生成随机token,并将其存放在session或者redis中,并将其返回给客户端
    • 客户端请求放重复提交接口时要带上此token(一般是存放至请求头中),服务器端将检验此token,若token能够在session或redis中查找到,则删除此token并放行接口,若没能查找到,说明不是第一次提交,则拒绝放行
    • 使用spring时可以利用AOP完成防重

    流程图:
    在这里插入图片描述

    展开全文
  • 本篇文章主要介绍了springMVC中基于token防止表单重复提交方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  • 防止表单重复提交的方法(简单的token方式),内附实现代码及实现思路。
  • 本文实例讲述了PHP使用token防止表单重复提交的方法。分享给大家供大家参考,具体如下: <?php /* * PHP使用token防止表单重复提交 * 此处理方法纯粹是为了给初学者参考 */ session_start(); function set_token...
  • token-springMVC 防止重复提交
  • springmvc 用拦截器+token防止重复提交

    千次阅读 2018-09-07 14:09:49
     首先,防止用户重复提交有很多种方式,总体分为前端JS限制和后端限制,也一直是在后端控制的,第一次遇到这种问题是因为360无限网卡问题,双网卡都发出的请求(问题原因不明确,反正关闭笔记本360无限模块就好了)...

     

         首先,防止用户重复提交有很多种方式,总体分为前端JS限制和后端限制,也一直是在后端控制的,第一次遇到这种问题是因为360无限网卡问题,双网卡都发出的请求(问题原因不明确,反正关闭笔记本360无限模块就好了).第二次是因为业务人员重复点击导致的(异步提交的服务器响应慢,也没有控制按钮置灰),第三次是同权限两个用户并发操作了(没几个人的系统,竟然赶到一起了,这个背啊)。

      第一次解决这个问题的方案就是加锁,但是这部分业务操作的是核心数据,不会并发,数据量大也不允许多次操作。这块还是个单机操作。

            1.尝试锁定任务  (先定义一个重入锁作为入参)

            if(!tryLock(lock, opName,opFlag)){

                         renderText("当前有任务正在进行,不进行排队,请稍候再试!");

                         return;

                  }

        2.try catch 包围业务处理 finally  释放锁

        下面是尝试获取锁的方法

               public boolean tryLock(ReentrantLock lock,String opName,String opFlag) {

                  try {

                         if(lock.tryLock()){

                               logger.info("【"+opName+"-锁定】:" + opFlag);

                               return true;

                         }

                         return false;

                  } catch (Exception e) {

                         logger.info("操作标识:"+opFlag+"------"+opName+"锁定异常!",e);

                         return false;

                  }

           }

    之后的业务没有什么限制了,就需要考虑多线程了,上述方案就不可行了。所以参考了其他人的方法,然后就是一番复制粘贴:

    正式代码开始:

    页面表单保存服务端发送的token

    <input id="token" name="token" type="hidden" th:value="${token}">

    首先自定义一个注解

    import java.lang.annotation.*;

    @Documented

    @Target(ElementType.METHOD)

    @Retention(RetentionPolicy.RUNTIME)

    public @interface Token {

    boolean save() default false;

    boolean remove() default false;

    }

    接着实现一个拦截器接口

    import java.io.PrintWriter;

    import java.lang.reflect.Method;

    import java.util.UUID;

    import javax.servlet.http.HttpServletRequest;

    import javax.servlet.http.HttpServletResponse;

    import com.bootdo.busi.utils.SendMsgUtil;

    import org.slf4j.Logger;

    import org.slf4j.LoggerFactory;

    import org.springframework.ui.Model;

    import org.springframework.web.context.request.RequestAttributes;

    import org.springframework.web.context.request.RequestContextHolder;

    import org.springframework.web.context.request.ServletRequestAttributes;

    import org.springframework.web.method.HandlerMethod;

    import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

     

    public class TokenInterceptor extends HandlerInterceptorAdapter {

    private static final Logger LOG = LoggerFactory.getLogger(Token.class);

    @Override

    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

    if (handler instanceof HandlerMethod) {

    HandlerMethod handlerMethod = (HandlerMethod) handler;

    Method method = handlerMethod.getMethod();

    Token annotation = method.getAnnotation(Token.class);

    if (annotation != null) {

    boolean needSaveSession = annotation.save();

    if (needSaveSession) {

    request.getSession(true).setAttribute("token", UUID.randomUUID().toString());

    }

    boolean needRemoveSession = annotation.remove();

    if (needRemoveSession) {

    if (isRepeatSubmit(request)) {

    LOG.warn("please don't repeat submit,url:"+ request.getServletPath());

    SendMsgUtil.sendMessage(response,"repetSubmit");

    return false;

    }

    request.getSession(true).removeAttribute("token");

    return false;

    }

    }

    return true;

    } else {

    return super.preHandle(request, response, handler);

    }

    }

     

    private boolean isRepeatSubmit(HttpServletRequest request) {

    String serverToken = (String) request.getSession(true).getAttribute("token");

    if (serverToken == null) {

    return true;

    }

    String clinetToken = request.getParameter("token");

    if (clinetToken == null) {

    return true;

    }

    if (!serverToken.equals(clinetToken)) {

    return true;

    }

    return false;

    }

    }

    返回页面数据工具

    import com.alibaba.fastjson.JSONObject;

    import com.alibaba.fastjson.serializer.SerializerFeature;

    import javax.servlet.http.HttpServletResponse;

    import java.io.PrintWriter;

    public class SendMsgUtil {

    /**

    * 发送消息 text/html;charset=utf-8

    * @param response

    * @param str

    * @throws Exception

    */

    public static void sendMessage(HttpServletResponse response, String str) throws Exception {

    response.setContentType("text/html; charset=utf-8");

    PrintWriter writer = response.getWriter();

    writer.print(str);

    writer.close();

    response.flushBuffer();

    }

    /**

    * 将某个对象转换成json格式并发送到客户端

    * @param response

    * @param obj

    * @throws Exception

    */

    public static void sendJsonMessage(HttpServletResponse response, Object obj) throws Exception {

    response.setContentType("application/json; charset=utf-8");

    PrintWriter writer = response.getWriter();

    writer.print(JSONObject.toJSONString(obj, SerializerFeature.WriteMapNullValue,

    SerializerFeature.WriteDateUseDateFormat));

    writer.close();

    response.flushBuffer();

    }

    }

    定义切面

    import org.aspectj.lang.JoinPoint;

    import org.aspectj.lang.ProceedingJoinPoint;

    import org.aspectj.lang.annotation.*;

    import org.springframework.stereotype.Component;

    @Component

    @Aspect

    public class TokenAspect {

    @Pointcut("@annotation(com.bootdo.busi.Token)")

    private void token() { }

    // /**

    // * 定制一个环绕通知

    // * @param joinPoint

    // */

    // @Around("token()")

    // public void advice(ProceedingJoinPoint joinPoint) throws Throwable {

    // System.out.println("Around Begin");

    // joinPoint.proceed();//执行到这里开始走进来的方法体(必须声明)

    // System.out.println("Around End");

    // }

     

    //当想获得注解里面的属性,可以直接注入改注解

    //方法可以带参数,可以同时设置多个方法用&&

    @Before("token()")

    public void record(JoinPoint joinPoint) {

    System.out.println("Before");

    }

    //

    // @After("token()")

    // public void after() {

    // System.out.println("After");

    // }

    }

     

    然后配置拦截器, WebConfigurer 中进行配置。

    import org.springframework.beans.factory.annotation.Autowired;

    import org.springframework.context.annotation.Bean;

    import org.springframework.stereotype.Component;

    import org.springframework.web.servlet.HandlerInterceptor;

    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;

    import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;

    import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

    @Component

    class WebConfigurer extends WebMvcConfigurerAdapter {

    @Autowired

    BootdoConfig bootdoConfig;

    @Override

    public void addResourceHandlers(ResourceHandlerRegistry registry) {

    registry.addResourceHandler("/files/**").addResourceLocations("file:///"+springbootConfig.getUploadPath());

    }

    @Override

    public void addInterceptors(InterceptorRegistry registry) {

    registry.addInterceptor(getMyInterceptor()).addPathPatterns("/**");

    super.addInterceptors(registry);

    }

    @Bean

    public HandlerInterceptor getMyInterceptor() {

    return new TokenInterceptor();

    }

    }

     

    最最最重要得一点一定要保证页面和后台token得正常传递!!!

    在需要生成token(通常是要点击提交得那个页面)得Controller中使用我们刚才自定义好得注解,贴代码:

    注:此处为请求的controller (跳转页面),save为true 是在服务端生成一个token 并发送给前端。此时remove默认为false。只进行生成token 不进行重复判断。在isRepeatSubmit方法判断通过返回后,清空服务端token,当重复请求时

    服务端token是空,与前端返回token不一致。

    @SuppressWarnings({ "unchecked", "finally", "rawtypes" })

    @RequestMapping("/SaveDataController/show")

    @Token(save=true)

    public String saveData(HttpServletRequest request,HttpServletResponse response,String task_id){

    Map map = new HashMap();

    System.out.println(task_id);

    try {

    map = saveDataService.queryByTaskId(task_id);

    } catch (Exception e) {

    e.printStackTrace();

    map.put("task_id", task_id);

    map.put("savetype", "");

    map.put("memoryCodes", "1");

    map.put("tablename", "");

    map.put("trowkey", "");

    map.put("columns", "");

    map.put("indextablename", "");

    map.put("irowkey", "");

    map.put("icolumns", "");

    } finally {

    request.setAttribute("map", map);

    return "savedata/index";

    }

    }

    只要通过这个方法跳向得页面都是随机生成一个token,然后再真正再提交触发得方法上加入@token(remove=true),贴代码:

    注:此处为处理业务请求的controller (跳转serivce),此时save默认为false 不会生成一个新的token。此时remove为true。判断当前服务端的token 与前端返回的token是否一致。一致的情况下正常处理

    @RequestMapping("/SaveDataController/saveData")

    @ResponseBody

    @Token(remove=true)

    public void saveData(HttpServletRequest request,HttpServletResponse response,

    String tablename,String trowkey,String columns,

    String indextablename,String irowkey,String icolumns,

    String task_id,String savetype,String memoryCodes){

    System.out.println(task_id);

    saveDataService.saveData(task_id,savetype,memoryCodes,tablename, trowkey, columns, indextablename, irowkey, icolumns);

    }

    js方法变更

     

    function submit01() {

    $.ajax({

    cache : true,

    type : "POST",

    url : prefix + "/save",

    data : $('#signupForm').serialize(),

    async : false,

    error : function(request) {

    laryer.alert("Connection error");

    },

    success : function(data) {

    if (data.code == 0) {

    parent.layer.msg("保存成功");

    parent.reLoad();

    var index = parent.layer.getFrameIndex(window.name); // 获取窗口索引

    parent.layer.close(index);

     

    } else {

    //这个位置增加了判断 判断是否为拦截器返回信息,是就进行重复提交提示

    //不是就按原有业务进行提示

    if(data=='repetSubmit'){

    layer.alert("请不要重复提交表单!")

    }else{

    layer.alert(data.msg)

    }

    }

    }

    });

    }

     

    但是,如果页面校验通过,后台校验不过呢,preHandle是业务执行前拦截,此时服务端的token已经被清除了,修改页面参数再提交就会提示重复提交了,用户刷新页面重新填写信息体验很不好。所以有几种方案可以预处理一下:

    1.提交表单前调用异步提交校验方法,通过后调用正式方法。

    2.校验不通过时,将页面token重新赋值给session。(不推荐,已经添加了拦截器和注解尽量不要修改其他代码)

    展开全文
  • 在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交。 一、表单重复...
  • 对于Token防止重复提交的个人思考

    千次阅读 2017-07-16 13:00:53
    如题,对于Token防止重复提交的个人思考 首先需要在表单的hidden区域放入name = token,value = 随机值,这一步实际是通过后台回传进入页面嵌入表单的 那么我大概想象几个重复提交的场景 场景1:我打开一个表单...
  • token令牌防止重复提交的问题

    千次阅读 2018-02-08 20:25:40
    那么就会造成数据重复提交,然后本人也专门去网上找了一些资料,然后集合自身的代码,胜利解决了此问题,本篇博文目的只是为了记录下这个东西,一方面是自己能把某一功能自己写下来的话可以加深自己的理解,另...
  • 主要介绍了详解struts2的token机制和cookie来防止表单重复提交的相关资料,需要的朋友可以参考下
  • 主要为大家详细介绍了Spring Boot如何防止重复提交,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 这样的红包链接或多或少都有很多的漏洞,就是表单可以重复提交。这样的话,对那些p2p网站或者其他类似的网站造成很大的损失。Fiddler大家都不陌生吧,就是一个抓包软件。我们先拦截url请求,Shift+R,填入压力测试的...
  • 如何利用token令牌防止表单重复提交

    千次阅读 2018-12-10 15:31:44
    如何利用token令牌防止表单重复提交,老规矩一步一步来。 第一步:写一个令牌生成器类, package com.accp.entity; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import ...
  • NULL 博文链接:https://minejava.iteye.com/blog/960617
  • PHP表单TOKEN防止重复提交

    千次阅读 2017-07-25 15:12:36
    PHP表单TOKEN防止重复提交一 简介1. 什么是表单token? Token(人家就叫这名,记住就行)是服务端生成的一串字符串,以作客户端进行请求的一个令牌和依据。 2. 表单token用来干什么? 第一:防止提交表单是为...
  • 那我们怎么利用token防止重复提交数据呢? 比如说:我们有三个controller方法:第一个是从主页跳转到用户管理页的userManger方法,然后是从用户管理页跳转到添加用户的 addUser方法,第三个是从接受表单页面提交...
  • 主要介绍了spring boot 防止重复提交实现方法,结合实例形式详细分析了spring boot 防止重复提交具体配置、实现方法及操作注意事项,需要的朋友可以参考下
  • 遇到问题: 测试人员用burpsuite工具抓取表单数据,当页面点击提交... 项目添加token验证,  第一步:先写token生成和销毁方法 token.java package com.smartt.api.interceptor; import java.lang.annotation.*;
  • 自定义封装注解类,(生成token存放到redis中)通过注解的方式解决API接口幂等设计防止表单重复提交
  • 主要介绍了PHP实现防止表单重复提交功能,结合实例形式分析了php基于token验证防止表单重复提交的相关操作技巧,非常简单实用,需要的朋友可以参考下
  • Java语言防止表单重复提交token机制

    千次阅读 2018-08-07 17:10:53
    防止用户注册信息或者订单信息重复提交写入数据库,使用session的token令牌机制 也叫做令牌机制,除了重定向以外的另一种处理表单重复提交的方法 login.jsp================================================ &...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 28,846
精华内容 11,538
关键字:

token防止重复登录

友情链接: FOXSYS.rar