AKSK鉴权示例

AKSK接口没有固定的格式,不想basic、apikey等简单的认证方式,请求格式是固定的。最主要的就是AKSK签名认证的工具类以及服务端校验格式。

定义 AKSK 相关的常量和工具类

首先,我们创建一些常量来表示访问密钥(AK)和秘密密钥(SK),以及用于签名的算法(这里使用 HMAC - SHA256)。

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class AkskUtils {

    // 模拟的访问密钥(AK)
    public static final String ACCESS_KEY = "your_access_key";

    // 模拟的秘密密钥(SK)
    public static final String SECRET_KEY = "your_secret_key";

    // 签名算法
    public static final String SIGNATURE_ALGORITHM = "HMACSHA256";

    public static String calculateSignature(String data) throws NoSuchAlgorithmException, InvalidKeyException {
        Mac mac = Mac.getInstance(SIGNATURE_ALGORITHM);
        SecretKeySpec secretKeySpec = new SecretKeySpec(SECRET_KEY.getBytes(StandardCharsets.UTF_8), SIGNATURE_ALGORITHM);
        mac.init(secretKeySpec);
        byte[] signatureBytes = mac.doFinal(data.getBytes(StandardCharsets.UTF_8));
        return bytesToHex(signatureBytes);
    }

    private static String bytesToHex(byte[] bytes) {
        StringBuilder result = new StringBuilder();
        for (byte b : bytes) {
            result.append(String.format("%02x", b));
        }
        return result.toString();
    }
}

 客户端实现

客户端负责构造请求,并添加鉴权相关的信息(如签名)到请求中。

import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.security.NoSuchAlgorithmException;
import java.security.InvalidKeyException;
import java.time.Duration;

public class AkskClient {

    public static void main(String[] args) throws IOException, InterruptedException, NoSuchAlgorithmException, InvalidKeyException {
        // 构造请求数据,这里简单模拟一个查询参数
        String queryParam = "param1=value1&param2=value2";
        String requestData = "GET&/api/resource?" + queryParam;

        // 计算签名
        String signature = AkskUtils.calculateSignature(requestData);

        // 构造完整的请求URL,添加签名作为查询参数
        String url = "http://localhost:8080/api/resource?" + queryParam + "&signature=" + signature;

        // 构造HTTP请求
        HttpRequest request = HttpRequest.newBuilder()
              .uri(URI.create(url))
              .header("Access-Key", AkskUtils.ACCESS_KEY)
              .timeout(Duration.ofSeconds(5))
              .build();

        // 发送请求
        HttpClient client = HttpClient.newHttpClient();
        HttpResponse<String> response = client.send(request, HttpResponse.BodyAndForestResponse<String>);

        // 处理响应
        System.out.println("Response status code: " + response.statusCode());
        System.out.println("Response body: " + response.body());
    }
}

 服务端实现

服务端负责接收客户端的请求,验证请求中的鉴权信息(如访问密钥和签名)是否合法。

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.security.NoSuchAlgorithmException;
import java.security.InvalidKeyException;

public class AkskServer {

    public static void main(String[] args) throws IOException, NoSuchAlgorithmException, InvalidKeyException {
        // 创建HTTP服务器,监听在本地的8080端口
        HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0);

        // 设置请求处理程序
        server.createContext("/api/resource", new MyHandler());

        // 启动服务器
        server.start();
        System.out.println("Server started on port 8080");
    }

    static class MyHandler implements HttpHandler {
        @Override
        public void handle(HttpExchange exchange) throws IOException {
            // 获取请求的查询参数
            String query = exchange.getRequestURI().getQuery();
            String[] queryParams = query.split("&");

            // 提取访问密钥、签名和其他参数
            String accessKey = null;
            String signature = null;
            String requestData = null;
            for (String param : queryParams) {
                if (param.startsWith("Access-Key=")) {
                    accessKey = param.substring("Access-Key=".length());
                } else if (param.startsWith("signature=")) {
                    signature = param.substring("signature=".length());
                } else {
                    requestData = (requestData == null)? param : requestData + "&" + param;
                }
            }

            // 验证访问密钥是否正确
            if (!AkskUtils.ACCESS_KEY.equals(accessKey)) {
                sendErrorResponse(exchange, 401, "Invalid access key");
                return;
            }

            // 重新计算签名,用于和客户端传来的签名对比
            String calculatedSignature = AkskUtils.calculateSignature(requestData);

            // 验证签名是否正确
            if (!calculatedSignature.equals(signature)) {
                sendErrorResponse(exchange, 403, "Invalid signature");
                return;
            }

            // 如果鉴权通过,发送成功响应
            sendSuccessResponse(exchange);
        }

        private void sendErrorResponse(HttpExchange exchange, int statusCode, String message) throws IOException {
            byte[] errorBytes = message.getBytes();
            exchange.sendResponseHeaders(statusCode, errorBytes.length);
            OutputStream os = exchange.getResponseBody();
            os.write(errorBytes);
            os.close();
        }

        private void sendSuccessResponse(HttpExchange exchange) throws IOException {
            byte[] successBytes = "Authenticated successfully".getBytes();
            exchange.sendResponseHeaders(200, successBytes.length);
            OutputStream os = exchange.getResponseBody();
            os.write(successBytes);
            os.close();
        }
    }
}

实际应用中可能需要更复杂的处理,比如对请求数据的更规范整理、更好的错误处理、更安全的密钥管理等,但大致思想就是这样的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值