第三方单点登录的接口编写
结合自身项目中的一个案列来编写第三方单点登录接口,目的是让第三方系统调用我们的接口,无需再次登录,跳转到我们的系统,我们系统自动帮用户进行登录
这个接口需要写两个,第一个则需要生成token,token的作用是防止第三方恶意登录以及会话过期。结合我个人案列的场景,这个案例是图书馆,用户现在在第三方登录,跳到图书馆系统,调用我们这个接口。
这里使用des加密参数生成token。
代码如下,第一个接口:
/** * 校验身份和生成token * * @param cardNO 卡号 * @param idcardNO 身份证号 * @param signatrue 签名 * @param timestamp 时间戳 * @param type 登录设备类型 * @return */ @RequestMapping("/createToekn") @ResponseBody public ResultEntity createToken(String cardNO, String idcardNO, @RequestParam(required = true) String signatrue, @RequestParam(required = true) String timestamp, @RequestParam(required = true) String type) { //根据参数名进行排序 SortedMap<String, String> parameterMap = new TreeMap<>(); parameterMap.put("cardNO", cardNO); parameterMap.put("idcardNO", idcardNO); parameterMap.put("timestamp", timestamp); parameterMap.put("type", type); StringBuffer sb = new StringBuffer(); Set es = parameterMap.entrySet(); //所有参与传参的参数按照accsii排序(升序) Iterator it = es.iterator(); while (it.hasNext()) { Map.Entry entry = (Map.Entry) it.next(); Object v = entry.getValue(); //空值不传递,不参与签名组串 if (null != v && !"".equals(v)) { sb.append(v); } } ResultEntity result = new ResultEntity(); //排序好的参数进行MD5加密 String md5Str = MD5Util.md5(sb + secretKey); if (md5Str.equals(signatrue)) { //验证通过,使用des生成token返回 //判断时间戳,超过120分钟,认证超时 Long currTime = System.currentTimeMillis(); if ((currTime - Long.parseLong(timestamp)) / (1000 * 60) > 120) { //这里设置签名只有两个小时有效时间,超过需要重新请求,这个第三方请求则需要将参数易进行accsii排序(升序),然后MD5加密,将sign传值过来再次认证 result.setState(HttpCode.FAILED); result.setMessage("认证超时,请重新请求!"); return result; } String jsonStr = JsonUtils.toJson(parameterMap); //使用des进行加密 DESPlus des = new DESPlus(); String token = des.encrypt(jsonStr); //返回token result.setResult(token); result.setMessage("认证通过!"); result.setState(HttpCode.SUCCESS); return result; } result.setMessage("认证失败!"); result.setState(HttpCode.FAILED); return result; }
第二个接口这需要验证token,验证通过了,则系统帮用户登录,验证不通过则跳到登录页面,让用户自行登录。
代码如下,第二个接口:
/** * 免密登录 */ @RequestMapping("/checkToken") public String checkToken(String token, HttpServletRequest request, HttpServletResponse response) { String cardNO = ""; String idcardNO = ""; String type = ""; String timestamp = ""; if (token != null && token != "") { try { //使用des解密 DESPlus des = new DESPlus(); String decStr = des.decrypt(token); //将字符串转换成map对象 Map<String, String> parameterMap = new HashMap<String, String>(); //将对象放到map中 parameterMap = JsonUtils.fromJson(decStr, Map.class); cardNO = parameterMap.get("cardNO"); idcardNO = parameterMap.get("idcardNO"); type = parameterMap.get("type"); timestamp = parameterMap.get("timestamp"); //判断时间有没有超过120分钟,超过即失效,跳转到登录界面 Long currTime = System.currentTimeMillis(); if ((currTime - Long.parseLong(timestamp)) / (1000 * 60) > 120) { //跳转到用户主页 if (type.equals("2")) { //跳转到微信端的界面 return "mobile/index"; } else { //默认跳转到pc端界面 return "pc/index"; } } if (cardNO != null || idcardNO != null) { //根据卡号或者身份证号去数据库查询用户信息 ReaderEntity param = new ReaderEntity(); param.setCardno(cardNO); param.setIdcardno(idcardNO); List<ReaderEntity> readerEntities = readerDao.selectByParam(param); if (!readerEntities.isEmpty()) { //存入session中,并且判断type pc:1,微信:2,然后跳转到各自首页 //创建session对象 HttpSession session = request.getSession(); session.setAttribute(USES_SESSION_ID, readerEntities.get(0)); //跳转到用户主页 if (type.equals("2")) { //跳转到微信端的界面 return "mobile/index"; } else { //默认跳转到pc端界面 return "pc/index"; } } } } catch (Exception e) { //报错直接跳转到登录界面 if (type.equals("2")) { //跳转到微信端的界面 return "mobile/index"; } else { //默认跳转到pc端界面 return "pc/index"; } } } //验证不通过,跳转到登录界面,type不传默认跳转到pc端登录 return "/pc/index"; }