身份验证模块
项目目录结构
1、新建maven工程
Group Id:org.apache.maven.archetypes
Artifact Id:maven-archetype-quickstart
Version:1.1
2、引入依赖
pom.xml
<groupId>pers.zhentao</groupId>
<artifactId>Validator</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>Validator</name>
<url>http://maven.apache.org</url>
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
<forceJavacCompilerUse>true</forceJavacCompilerUse>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-lambda-java-core</artifactId>
<version>1.1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.38</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.6</version>
</dependency>
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.7.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-lambda -->
<dependency>
<groupId>com.amazonaws</groupId>
<artifactId>aws-java-sdk-lambda</artifactId>
<version>1.11.221</version>
</dependency>
</dependencies>
3、lambda函数输入POJO
RequestInfo.java
/** * 请求封装 * * @author zhangzhentao1995@163.com * 2017-10-30 */
public class RequestInfo {
public static final int TARGET_ADD_RECORD = 3001;
public static final int TARGET_DELETE_RECORD = 3002;
public static final int TARGET_QUERY_RECORD = 3003;
/** * token */
private String token;
/** * 目标接口 */
private int target;
/** * 参数Json */
private String paramJson;
//getters and setters...
}
4、lambda函数输出POJO
ResponseData.java
/** * 返回消息 * * @author zhangzhentao1995@163.com * 2017-10-30 */
public class ResponseData {
public static final Integer RESPONSE_CODE_SUCCESS = 1000;
public static final Integer RESPONSE_CODE_ERROR = 1001;
public static final Integer RESPONSE_CODE_SYS_EXCEPTION = 1002;
private Integer code;
private String message;
private List<Record> rows;
private Map<Object, Object> map;
public ResponseData(Integer code, String message) {
this.code = code;
this.message = message;
}
public ResponseData(Integer code, List<Record> rows) {
this.rows = rows;
this.code = code;
}
//getters and setters...
}
5、lambda处理程序
LambdaFunctionHandler.java
/** * lambda处理程序 * * @author zhangzhentao1995@163.com * 2017-10-30 */
public class LambdaFunctionHandler implements RequestHandler<RequestInfo, ResponseData> {
private static String awsAccessKeyId = null;
private static String awsSecretAccessKey = null;
private static String regionName = null;
private static String jwtSecret = null;
public ResponseData handleRequest(RequestInfo input, Context context) {
LambdaLogger logger = context.getLogger();
awsAccessKeyId = System.getenv("ACCESS_KEY");
awsSecretAccessKey = System.getenv("SECRET_KEY");
regionName = System.getenv("REGION");
jwtSecret = System.getenv("JWT_SECRET");
if(awsAccessKeyId == null || awsSecretAccessKey == null || regionName == null) {
return new ResponseData(ResponseData.RESPONSE_CODE_ERROR, "aws config is null.");
}
if(jwtSecret == null) {
return new ResponseData(ResponseData.RESPONSE_CODE_ERROR, "jwtSecret is null.");
}
logger.log("[" + new Date() + "]RequestInfo:" + JSONObject.toJSONString(input));
User user = TokenUtil.validateToken(input.getToken(), jwtSecret);
logger.log("[" + new Date() + "]user:" + JSONObject.toJSONString(user));
if (user == null) {
return new ResponseData(ResponseData.RESPONSE_CODE_ERROR, "invalid token.");
} else {
AWSCredentials credentials = new BasicAWSCredentials(awsAccessKeyId, awsSecretAccessKey);
AWSStaticCredentialsProvider provider = new AWSStaticCredentialsProvider(credentials);
LambdaFunctions functions = LambdaInvokerFactory.builder().lambdaClient(
AWSLambdaAsyncClientBuilder.standard().withCredentials(provider).withRegion(regionName).build())
.build(LambdaFunctions.class);
switch (input.getTarget()) {
case RequestInfo.TARGET_ADD_RECORD:
try {
Record record = JSONObject.parseObject(input.getParamJson(), Record.class);
record.setCreatedBy(user.getUserId());
Object addRecordResponse = functions.AddRecord(record);
logger.log("[" + new Date() + "]invoke addRecordFunction:"
+ JSONObject.toJSONString(addRecordResponse));
return new ResponseData(
JSONObject.parseObject(JSONObject.toJSONString(addRecordResponse)).getInteger("code"),
JSONObject.parseObject(JSONObject.toJSONString(addRecordResponse)).getString("message"));
} catch (Exception e) {
logger.log("[" + new Date() + "]exception:" + e.getMessage());
return new ResponseData(ResponseData.RESPONSE_CODE_ERROR, "invalid input.");
}
case RequestInfo.TARGET_DELETE_RECORD:
Object deleteRecordResponse = functions.DeleteRecord(Integer.parseInt(input.getParamJson()));
logger.log("[" + new Date() + "]invoke deleteRecordFunction:"
+ JSONObject.toJSONString(deleteRecordResponse));
return new ResponseData(
JSONObject.parseObject(JSONObject.toJSONString(deleteRecordResponse)).getInteger("code"),
JSONObject.parseObject(JSONObject.toJSONString(deleteRecordResponse)).getString("message"));
case RequestInfo.TARGET_QUERY_RECORD:
try {
Record record2 = JSONObject.parseObject(input.getParamJson(), Record.class);
Object queryRecordResponse = functions.QueryRecord(record2);
logger.log("[" + new Date() + "]invoke queryRecordFunction:"
+ JSONObject.toJSONString(queryRecordResponse));
Integer code = JSONObject.parseObject(JSONObject.toJSONString(queryRecordResponse))
.getInteger("code");
if (code.equals(ResponseData.RESPONSE_CODE_SUCCESS)) {
return new ResponseData(code,
JSONObject.parseObject(JSONObject.toJSONString(queryRecordResponse)).getObject("rows",
List.class));
}
} catch (Exception e) {
logger.log("[" + new Date() + "]exception:" + e.getMessage());
return new ResponseData(ResponseData.RESPONSE_CODE_ERROR, "invalid input.");
}
default:
return new ResponseData(ResponseData.RESPONSE_CODE_ERROR, "invalid target.");
}
}
}
}
6、lambda调用接口
LambdaFunctions.java
/** * lambda接口 * * @author zhangzhentao1995@163.com * 2017-10-30 */
public interface LambdaFunctions {
/** * 调用添加接口 * * @param record * @return */
@LambdaFunction
Object AddRecord(Record record);
/** * 调用删除接口 * * @param id * @return */
@LambdaFunction
Object DeleteRecord(Integer id);
/** * 调用查询接口 * * @param record * @return */
@LambdaFunction
Object QueryRecord(Record record);
}
7、通讯录实体类
Record.java
/** * 通讯录实体类 * * @author zhangzhentao1995@163.com * 2017-10-30 */
public class Record {
private Integer addressBookId;
private String name;
private String phoneNumber;
private String address;
private String telephoneNumber;
private String note;
private Date createTime;
private Integer createdBy;
//getters and setters...
}
8、user实体类
User.java
/** * user dto * * @author zhangzhentao1995@163.com * 2017-10-30 */
public class User {
private Integer userId;
private String userName;
private String email;
private Date createDate;
//getters and setters...
}
9、JWT配置常量
Constant.java
/** * JWT配置常量 * * @author zhangzhentao1995@163.com * 2017-10-30 */
public class Constant {
public static final String JWT_ID = "jwt";
public static final int JWT_TTL = 60*60*1000;
public static final int JWT_REFRESH_INTERVAL = 55*60*1000;
public static final int JWT_REFRESH_TTL = 12*60*60*1000;
}
10、JWT封装工具类
JwtUtil.java
/** * JWT封装工具类 * * @author zhangzhentao1995@163.com * 2017-10-30 */
public class JwtUtil {
public static SecretKey generalKey(String jwtSecret) {
byte[] encodeKey = Base64.getDecoder().decode(jwtSecret);
SecretKey key = new SecretKeySpec(encodeKey, 0, encodeKey.length, "AES");
return key;
}
public static String createJwt(String id, String jwtSecret, String subject, long ttlMillis) throws Exception {
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
long nowMillis = System.currentTimeMillis();
Date now = new Date(nowMillis);
SecretKey key = generalKey(jwtSecret);
JwtBuilder builder = Jwts.builder().setId(id).setIssuedAt(now).setSubject(subject).signWith(signatureAlgorithm,
key);
if (ttlMillis >= 0) {
long expMillis = nowMillis + ttlMillis;
Date exp = new Date(expMillis);
builder.setExpiration(exp);
}
return builder.compact();
}
public static Claims parseJwt(String jwt, String jwtSecret) throws Exception {
SecretKey key = generalKey(jwtSecret);
Claims claims = Jwts.parser().setSigningKey(key).parseClaimsJws(jwt).getBody();
return claims;
}
public static String generalSubject(User user) {
JSONObject json = new JSONObject();
json.put("userId", user.getUserId());
json.put("userName", user.getUserName());
json.put("email", user.getEmail());
json.put("createDate", user.getCreateDate());
return json.toString();
}
}
11、token工具类
TokenUtil.java
/** * token工具类 * * @author zhangzhentao1995@163.com * 2017-10-30 */
public class TokenUtil {
public static User validateToken(String token, String jwtSecret) {
try {
Claims claims = JwtUtil.parseJwt(token, jwtSecret);
String subject = claims.getSubject();
User user = JSONObject.toJavaObject(JSONObject.parseObject(subject), User.class);
return user;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
public static String getToken(User user, String jwtSecret) {
String subject = JwtUtil.generalSubject(user);
String token = null;
try {
token = JwtUtil.createJwt(Constant.JWT_ID, jwtSecret, subject, Constant.JWT_TTL);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return token;
}
}
12、maven打包
mvn package
执行完成后,项目target文件夹下会出现jar包:XXXX-0.0.1-SNAPSHOT.jar
13、创建lambda函数,配置处理程序路径,配置环境变量,上传jar包
14、配置测试事件
测试Add:
测试Delete
测试Query
至此,身份验证模块lambda部分完成。
接下来进行API Gateway配置。
15、创建API
16、创建资源
(启用 API Gateway CORS,解决Ajax跨域访问问题)
17、创建方法,选择集成环境,选择区域和Lambda函数,保存
18、配置POST方法,配置方法响应,添加200的响应标头(解决Ajax跨域访问问题)
Access-Control-Allow-Origin
19、配置集成响应,设置响应标头映射值
标头:Access-Control-Allow-Origin
值(注意加入单引号):'*'
20、部署API
21、测试API
测试报文:
{
"username":"test",
"password":"test" }
查看测试结果是否正确。
22、使用相同方式配置资源:operation和register
至此,身份验证模块完成。