一个API就是一把开启神圣之门的钥匙.
只有我的子民才能拿着它,
进入我的王国中.
API裸奔,接口暴露, 大门敞开,任何人都可以进入…
接口参数加上公钥,是我发给子民的一把钥匙 . 当一个小偷, 在某个夜黑风高的晚上拿走了这把钥匙, 它也能瞥见我王国的一面.
然后我会在接口参数中再加上时间戳,这是一把带有时间属性的钥匙.只要过了一定的时间,这把钥匙就会失效.就算小偷拿了这把钥匙,时间一过,也就会不起作用.
然而,小偷勤快的,按时蹲点.还是成功的偷走既具时效性,也有公钥的钥匙.
最终, 我吩咐大门守卫,一定要对的上暗号的才能进入.这是加入私钥的签名.
以上, API接口参数加密+ 时效性检验+ 签名.
TestUserController .java
/**
* @Title: TestUserController.java
* @Package com.jzt.ssm.controller
*
* @author jzt
* @date 2018-11-15
* @version V1.0
*/
package com.jzt.ssm.controller;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.jzt.ssm.po.Result;
import com.jzt.ssm.po.UserCustom;
import com.jzt.ssm.service.UserinfoService;
import com.jzt.ssm.util.MD5;
/**
* @ClassName: TestUserController
*
* @author jzt
* @date 2018-11-15
*
*/
@Controller
public class TestUserController {
@Autowired
private UserinfoService userinfoService;
/**
*
*
* 用户登录
* @Title: userLogin
*
* @param user(用户名+密码+公钥+时间戳)
* @return 登录成功,true,否则 false
*
* @author jzt
* @throws Exception
*/
@RequestMapping("/userLogin")
public @ResponseBody Result userLogin(UserCustom user) throws Exception{
Result result = new Result();
//获得时间戳
Date timeStamp = user.getTimeStamp();
Map<String,String> keys = new HashMap<>();
Date date = new Date();
if(user.getTimeStamp()==null||timeStamp.getTime()==0||timeStamp.getTime()+ 20000 > date.getTime()){//接口时间失效
result.setMessage("接口时效失效");
result.setReturnCode(-1);
}
if(user.getAccessKey()==null||user.getAccessKey()==""||!keys.containsKey(user.getAccessKey())){ //后台没有该公钥
result.setMessage("后台没有该公钥");
result.setReturnCode(-2);
}
//公钥 + 私钥
keys.put("zhangshan", "sdjfkasdgnkdkgdkjdlkg");
keys.put("lisi", "sddsgjgjkljdgdjjgkfdkfdg");
//使用TreeMap进行升序排
Map<String,Object> params = new TreeMap<>();
if(user.getAccessKey()!=null) params.put("accessKey", user.getAccessKey());
if(user.getPassWd()!=null) params.put("passWd", user.getPassWd());
if(user.getTimeStamp()!=null) params.put("timeStamp", user.getTimeStamp());
if(user.getUserName()!=null) params.put("userName", user.getUserName());
params.put("secretKey", keys.get(user.getAccessKey()));
String paramsStr = "";
Set<String> keySet = params.keySet();
Iterator<String> it = keySet.iterator();
while(it.hasNext()){
Object key = it.next();
Object value = params.get(key);
paramsStr+= key+ "=" + value +"&";
}
paramsStr = paramsStr.substring(0,paramsStr.length()-1);
String sign = MD5.encodeByMD5(paramsStr).toUpperCase();
if(!sign.equals(user.getSign())){
result.setMessage("签名失败");
result.setReturnCode(-3);
}
Boolean checklogin = userinfoService.checklogin(user.getUserName(), user.getPassWd());
if(checklogin){
result.setMessage("登录成功");
result.setReturnCode(1);
}else{
result.setMessage("用户或密码错误");
result.setReturnCode(0);
}
return result;
}
}
MD5.java
/**
* @Title: MD5.java
* @Package com.jzt.ssm.util
*
* @author jzt
* @date 2018-11-15
* @version V1.0
*/
package com.jzt.ssm.util;
import java.security.MessageDigest;
/**
* @ClassName: MD5
*
* @author jzt
* @date 2018-11-15
*
*/
public class MD5 {
/** 十六进制下数字到字符的映射数组 */
private final static String[] hexDigits = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" };
/**
* 对字符串进行MD5编码
* @param originString
* @return
*/
public static String encodeByMD5(String originString) {
if (originString != null){
try {
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] results = md.digest(originString .getBytes());
String resultString = byteArrayToHexString(results);
return resultString.toUpperCase();
} catch (Exception ex) {
ex.printStackTrace();
}
}
return null;
}
/**
* 转换字节数组为16进制字串
*
* @param b 字节数组
* @return 十六进制字串
*/
private static String byteArrayToHexString(byte[] b) {
StringBuffer resultSb = new StringBuffer();
for (int i = 0; i < b.length; i++) {
resultSb.append(byteToHexString(b[i]));
}
return resultSb.toString();
}
/**
* 将一个字节转化成16进制形式的字符串
* @param b
* @return
*/
private static String byteToHexString(byte b) {
int n = b;
if (n < 0)
n = 256 + n;
int d1 = n / 16;
int d2 = n % 16;
return hexDigits[d1] + hexDigits[d2];
}
}
User.java和UserCustom.java
/**
* @Title: User.java
* @Package com.jzt.ssm.po
*
* @author jzt
* @date 2018-11-15
* @version V1.0
*/
package com.jzt.ssm.po;
/**
* @ClassName: User
*
* @author jzt
* @date 2018-11-15
*
*/
public class User {
private String userName;
private String passWd;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public String getPassWd() {
return passWd;
}
public void setPassWd(String passWd) {
this.passWd = passWd;
}
}
/**
* @Title: UserCustom.java
* @Package com.jzt.ssm.po
*
* @author jzt
* @date 2018-11-15
* @version V1.0
*/
package com.jzt.ssm.po;
import java.util.Date;
/**
* @ClassName: UserCustom
*
* @author jzt
* @date 2018-11-15
*
*/
public class UserCustom extends User {
//时间戳
private Date timeStamp;
//公钥
private String accessKey;
//签名
private String sign;
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public Date getTimeStamp() {
return timeStamp;
}
public void setTimeStamp(Date timeStamp) {
this.timeStamp = timeStamp;
}
public String getAccessKey() {
return accessKey;
}
public void setAccessKey(String accessKey) {
this.accessKey = accessKey;
}
}
Result.java
/**
* @Title: Result.java
* @Package com.jzt.ssm.po
*
* @author jzt
* @date 2018-11-15
* @version V1.0
*/
package com.jzt.ssm.po;
/**
* @ClassName: Result
*
* @author jzt
* @date 2018-11-15
*
*/
public class Result {
private String message;
private int returnCode;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public int getReturnCode() {
return returnCode;
}
public void setReturnCode(int returnCode) {
this.returnCode = returnCode;
}
}