在Java中用API Key进行认证
通常情况下,在网络应用中,我们会使用一个用户名(电子邮件ID/登录名)和一个密码来登录。我们也可以通过使用APIKey来实现安全登录。让我们看看什么是APIKey。API密钥是一个唯一的标识符,用于验证请求,如果有几个用户,他们的用户名或电子邮件ID可以与当前日期和一个安全代码结合起来,只为该项目使用md5机制,我们可以创建APIKey并可以在数据库中维护。让 我们看看创建APIKey和将其插入数据库的方法。
项目实例
MySQL表结构。
-- Sample table named users is available
CREATE TABLE `users` (
`userId` int(11) NOT NULL AUTO_INCREMENT,
`loginId` varchar(20) DEFAULT NULL,
apiKey varchar(255) DEFAULT NULL,
PRIMARY KEY (`userId`)
);
-- insert 2 records
insert into users (loginId) values ('geeka@gmail.com');
insert into users (loginId) values ('geekb@gmail.com');

现在让我们看看创建API密钥并将其更新到 "用户"(MySQL)表中的示例java程序
Java
import static java.nio.charset.StandardCharsets.UTF_8;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.sql.*;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class CreateAndUpdateAPIKey {
Connection conn;
// To generate MD5 hashvalue
public String generateMD5Hashvalue(String userName)
{
LocalDate dateObj = LocalDate.now();
DateTimeFormatter formatter
= DateTimeFormatter.ofPattern("yyyyMMdd");
String date = dateObj.format(formatter);
MessageDigest md;
try {
md = MessageDigest.getInstance("MD5");
}
catch (NoSuchAlgorithmException e) {
throw new IllegalArgumentException(e);
}
String secretPhase
= "geeks"; // exclusively to set for geeks
System.out.println("Current Date : " + date);
System.out.println("Login Id : " + userName);
System.out.println("Secret Phase : " + secretPhase);
// By using the current date, userName(emailId) and
// the secretPhase , it is generated
byte[] hashResult
= md.digest((date + userName + secretPhase)
.getBytes(UTF_8));
// convert the value to hex
String password = bytesToHex(hashResult);
System.out.println("Generated password.."
+ password);
return password;
}
private String bytesToHex(byte[] bytes)
{
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
public static void main(String[] args)
{
// let us assume there is a table 'users' available
// By passing as an argument, we can have that for
// any table
new CreateAndUpdateAPIKey("users");
}
public CreateAndUpdateAPIKey(String tableName)
{
try {
// connecting to mySQL
Class.forName("com.mysql.jdbc.Driver")
.newInstance();
String url
= "jdbc:mysql://localhost/geeksforgeeks?useUnicode=true&characterEncoding=utf-8";
conn = DriverManager.getConnection(url, "root",
"admin");
doSelectAndUpdate(tableName);
conn.close();
}
catch (ClassNotFoundException ex) {
System.err.println(ex.getMessage());
}
catch (IllegalAccessException ex) {
System.err.println(ex.getMessage());
}
catch (InstantiationException ex) {
System.err.println(ex.getMessage());
}
catch (SQLException ex) {
System.err.println(ex.getMessage());
}
}
private void doSelectAndUpdate(String tableName)
{
doSelect(tableName);
}
private void doSelect(String tableName)
{
String query = null, userName = null;
// Query the respective table. If multiple tables
// are possible, then we should have separate if or
// switch statements
query = "SELECT * FROM users";
try {
Statement st = conn.createStatement();
ResultSet rs = st.executeQuery(query);
while (rs.next()) {
// loginId is the unique column to identify
// the user
userName = rs.getString("loginId");
// Get the MD5 value and get as password
String password
= generateMD5Hashvalue(userName);
// update the password
doUpdate(password, userName, tableName);
System.out.println(userName + ":"
+ password);
}
}
catch (SQLException ex) {
System.err.println(ex.getMessage());
}
}
private void doUpdate(String apiKey, String userName,
String tableName)
{
System.out.print("\n[Performing UPDATE] ... ");
try {
Statement st = conn.createStatement();
// Use the generated password for apiKey
String sqlUpdate = null;
sqlUpdate = "UPDATE users "
+ "SET apikey = ? "
+ "WHERE loginId = ?";
PreparedStatement pstmt
= conn.prepareStatement(sqlUpdate);
pstmt.setString(1, apiKey);
pstmt.setString(2, userName);
int rowAffected = pstmt.executeUpdate();
System.out.println(String.format(
"Row affected %d", rowAffected));
}
catch (SQLException ex) {
System.err.println(ex.getMessage());
}
}
}
在执行上述程序时,我们可以看到下面的输出 我们也可以看到API密钥在MySQL中的更新情况。

现在让我们尝试使用登录ID和apiKey登录到样本中。最重要的是apiKey将在每天的基础上因为日期而被改变。为了实现这一点,这段java代码需要作为 "CRON "作业放在Linux服务器上。我们可以有一个JSP页面的样本,在那里我们应该有键入loginId和apiKey的规定。
HTML
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Login Form With APIKey</title>
</head>
<body>
<div align="center">
<h1>Login Form - API KEY</h1>
<form action="<%=request.getContextPath()%>/login" method="post">
<table style="with: 100%">
<tr>
<td>Login</td>
<td><input type="text" name="loginId" /></td>
</tr>
<tr>
<td>APIKEY</td>
<td><input type="password" name="apiKey" /></td>
</tr>
</table>
<input type="submit" value="Submit" />
</form>
</div>
</body>
</html>

一旦收到信息,它将被存储在Bean中并得到验证。让我们来看看验证的部分。
LoginWithAPIKeyDao.java
Java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import net.gfg.login.bean.LoginBean;
public class LoginWithAPIKeyDao {
public boolean validate(LoginBean loginBean)
throws ClassNotFoundException
{
boolean status = false;
Class.forName("com.mysql.jdbc.Driver");
try {
Connection connection = DriverManager.getConnection(
"jdbc:mysql://localhost:3306/geeksforgeeks?useSSL=false",
"root", "admin");
// We have to query the users table with the
// passed information
PreparedStatement preparedStatement
= connection.prepareStatement(
"select * from users where loginId = ? and apiKey = ?");
preparedStatement.setString(
1, loginBean.getLoginId());
preparedStatement.setString(
2, loginBean.getApiKey());
ResultSet rs = preparedStatement.executeQuery();
// For the given query, if there is a record
while (rs.next()) {
status = true; // make the status to true
}
}
catch (SQLException e) {
// process sql exception
displaySQLException(e);
}
return status;
}
private void displaySQLException(SQLException ex)
{
// for (Throwable e : ex) {
if (ex instanceof SQLException) {
ex.printStackTrace(System.err);
System.err.println(
"SQLState: "
+ ((SQLException)ex).getSQLState());
System.err.println(
"Error Code: "
+ ((SQLException)ex).getErrorCode());
System.err.println("Message: "
+ ex.getMessage());
Throwable t = ex.getCause();
while (t != null) {
System.out.println("Cause: " + t);
t = t.getCause();
}
}
// }
}
}
然后,它将被重定向到成功页面或进一步的机制。

总结
在这篇文章中,我们看到了如何通过使用MD5 机制来生成APIKey,以及如何使用loginId/apiKey来登录到一个应用程序。
