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

2019-04-18  本文已影响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);
    }

}
上一篇下一篇

猜你喜欢

热点阅读