美文网首页
HelloWorld -- 扫码登录(客户端轮训)

HelloWorld -- 扫码登录(客户端轮训)

作者: 迷狮 | 来源:发表于2019-04-18 09:31 被阅读0次

    扫码登录-客户端定时器轮训实现

    源码地址:https://gitee.com/HQSONG/helloworld.git

    controller接口

    详细可参考源代码。cn.codersnet.helloworld.scanlogin.web.ScanLoginController

    @RestController
    @RequestMapping("/scanlogin")
    public class ScanLoginController {
    
        private Log logger = LogFactory.getLog(this.getClass());
        
        private static final String TOKEN_LOGINID_SUFFIX = "_loginID";
        @Autowired
        private Cache cache;
        
        /**
         * 生成二维码,暂时返回token
         * @return
         */
        @GetMapping("/generate")
        public String generateCrCode() {
            //生成token
            String token = UUID.randomUUID().toString();
            //将token置于缓存中,可以设置默认有效期,可以直接使用redis缓存设置过期时间。这里简单通过map实现
            cache.put(token, new ScanStatus(ScanStatus.CODE_GENERATE, "二维码已生成, 待扫描"), 60); //60s后过期
            return token;
        }
        
        /**
         * 移动端扫码
         * @return
         */
        @GetMapping("/appScan")
        public ScanStatus appScan(String token) {
            
            ScanStatus status = new ScanStatus(ScanStatus.CODE_SCANED, "二维码已扫描, 待确认");
            if(cache.existed(token)) {
                cache.put(token, status);
            } else {
                status.setStatusCode(ScanStatus.CODE_EXPIRED);
                status.setMessage("二维码已过期或不存在");
            }
            return status;
        }
        
        /**
         * 移动端确认登录,如果存在token未过期,设置token和loginID关联关系
         * @param token
         * @param loginID
         * @return
         */
        @GetMapping("/appConfirm")
        public ScanStatus appConfirm(String token, String loginID) {
            ScanStatus status = new ScanStatus(ScanStatus.CODE_APP_CONFIRM, "移动端已确认");
            if(cache.existed(token)) {
                cache.put(token, status);
                cache.put(token + TOKEN_LOGINID_SUFFIX, loginID);
            } else {
                status.setStatusCode(ScanStatus.CODE_EXPIRED);
                status.setMessage("二维码已过期或不存在");
            }
            return status;
        }
        
        /**
         * 检查扫码状态
         * @param token
         * @return
         */
        @PostMapping("/check")
        public ScanStatus check(String token) {
            
            if(cache.existed(token)) {
                ScanStatus scanStatus = (ScanStatus)cache.get(token);
                if(ScanStatus.CODE_APP_CONFIRM == scanStatus.getStatusCode()) {
                    //TODO 执行登录
                    String loginID = (String)cache.get(token + TOKEN_LOGINID_SUFFIX); 
                    logger.info(loginID + ", app扫描登录成功");
                    return new ScanStatus(ScanStatus.CODE_LOGIN_SUCCESS, "登录成功");
                } else {
                    return scanStatus;
                }
            } 
            //二维码过期
            cache.remove(token + TOKEN_LOGINID_SUFFIX);
            return new ScanStatus(ScanStatus.CODE_EXPIRED, "二维码已过期或不存在");
        }
    }
    

    单元测试

    详细可参考源代码。cn.codersnet.helloworld.ScanLoginTests

    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = HelloworldApplication.class)
    @AutoConfigureMockMvc
    public class ScanLoginTests {
    
        @Autowired
        private MockMvc mvc;
        
        private JacksonTester<ScanStatus> json;
    
         @Before
         public void setup() {
             ObjectMapper objectMapper = new ObjectMapper();
             JacksonTester.initFields(this, objectMapper);
         }
        /**
         * 扫码登录测试测试方法
         * @throws Exception
         */
        @Test
        public void scanLoginSuccessTest() throws Exception {
            // 1. 获取token(二维码)
            String token = mvc.perform(get("/scanlogin/generate")).andReturn().getResponse().getContentAsString();
            Assert.isTrue(check(token).getStatusCode() == ScanStatus.CODE_GENERATE, "生成二维码失败");
            // 2. 移动端扫码
            mvc.perform(get("/scanlogin/appScan").param("token", token));
            Assert.isTrue(check(token).getStatusCode() == ScanStatus.CODE_SCANED, "扫码失败");
            // 3. 移动端确认登录
            mvc.perform(get("/scanlogin/appConfirm").param("token", token).param("loginID", "test01"));
            // 4. PC端登录成功
            Assert.isTrue(check(token).getStatusCode() == ScanStatus.CODE_LOGIN_SUCCESS, "登录失败");
        }
        /**
         * 扫码登录超时测试方法,示例代码中超时时间为60s
         * @throws Exception
         */
        @Test
        public void scanLoginTimeoutTest() throws Exception {
            // 1. 获取token(二维码)
            String token = mvc.perform(get("/scanlogin/generate")).andReturn().getResponse().getContentAsString();
            Assert.isTrue(check(token).getStatusCode() == ScanStatus.CODE_GENERATE, "生成二维码失败");
            //2. 等待超时
            Thread.sleep(60*1000);
            //3. PC端check验证
            Assert.isTrue(check(token).getStatusCode() == ScanStatus.CODE_EXPIRED, "超时校验失败");
            //4. 移动端扫码验证
            mvc.perform(get("/scanlogin/appScan").param("token", token));
            Assert.isTrue(check(token).getStatusCode() == ScanStatus.CODE_EXPIRED, "超时校验失败");
        }
        
    
        private ScanStatus check(String token) throws Exception {
            String checkStr = mvc.perform(post("/scanlogin/check").param("token", token)).andReturn().getResponse()
                    .getContentAsString();
            return this.json.parseObject(checkStr);
        }
    
    }
    

    相关文章

      网友评论

          本文标题:HelloWorld -- 扫码登录(客户端轮训)

          本文链接:https://www.haomeiwen.com/subject/jrtzwqtx.html