认证 请求/响应 封装

This commit is contained in:
shikong 2023-09-26 16:52:34 +08:00
parent 41c8480ae0
commit d875a90fd6
6 changed files with 207 additions and 77 deletions

View File

@ -0,0 +1,20 @@
package cn.skcks.docking.gb28181.sip.method.register;
import lombok.*;
import lombok.experimental.SuperBuilder;
import javax.sip.message.Request;
@SuperBuilder
@Data
public class RegisterBuilder {
@Getter
private static final String method = Request.REGISTER;
private String localIp;
private int localPort;
private String localId;
private String targetIp;
private int targetPort;
private String targetId;
private String transport;
}

View File

@ -0,0 +1,53 @@
package cn.skcks.docking.gb28181.sip.method.register.request;
import cn.skcks.docking.gb28181.sip.generic.SipBuilder;
import cn.skcks.docking.gb28181.sip.generic.SipRequestBuilder;
import cn.skcks.docking.gb28181.sip.method.register.RegisterBuilder;
import cn.skcks.docking.gb28181.sip.utils.DigestAuthenticationHelper;
import cn.skcks.docking.gb28181.sip.utils.SipUtil;
import gov.nist.javax.sip.message.SIPRequest;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.SneakyThrows;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
import lombok.extern.slf4j.Slf4j;
import javax.sip.address.Address;
import javax.sip.address.SipURI;
import javax.sip.header.AuthorizationHeader;
import javax.sip.header.WWWAuthenticateHeader;
import javax.sip.message.Request;
@Slf4j
@Data
@SuperBuilder
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class RegisterRequestBuilder extends RegisterBuilder {
public Request createNoAuthorizationRequest(String callId, int expires) {
String local = SipBuilder.createHostAddress(getLocalIp(), getLocalPort());
Address localAddress = SipBuilder.createAddress(SipBuilder.createSipURI(getLocalId(), local));
String target = SipBuilder.createHostAddress(getTargetIp(), getTargetPort());
SipURI targetUri = SipBuilder.createSipURI(getTargetId(), target);
Request request = SipRequestBuilder.createRequest(targetUri, getMethod(),
SipBuilder.createCallIdHeader(callId),
SipBuilder.createCSeqHeader(1L, getMethod()),
SipBuilder.createFromHeader(localAddress, SipUtil.generateFromTag()),
SipBuilder.createToHeader(localAddress),
SipBuilder.createViaHeaders(getTargetIp(), getTargetPort(), getTransport(), SipUtil.generateViaTag()),
SipBuilder.createMaxForwardsHeader(70));
return SipBuilder.addHeaders(request,
SipBuilder.createExpiresHeader(expires),
SipBuilder.createContactHeader(localAddress));
}
@SneakyThrows
public Request createAuthorizationRequest(String callId, int expires, String id, String passwd, WWWAuthenticateHeader wwwAuthenticateHeader) {
SIPRequest request = (SIPRequest) createNoAuthorizationRequest(callId, expires);
request.getCSeq().setSeqNumber(2L);
AuthorizationHeader authorization = DigestAuthenticationHelper.createAuthorization(getMethod(), getTargetIp(), getTargetPort(), getTargetId(), id, passwd, wwwAuthenticateHeader);
return SipBuilder.addHeaders(request,authorization);
}
}

View File

@ -0,0 +1,65 @@
package cn.skcks.docking.gb28181.sip.method.register.response;
import cn.skcks.docking.gb28181.sip.generic.SipBuilder;
import cn.skcks.docking.gb28181.sip.generic.SipResponseBuilder;
import cn.skcks.docking.gb28181.sip.method.register.RegisterBuilder;
import cn.skcks.docking.gb28181.sip.utils.DigestAuthenticationHelper;
import cn.skcks.docking.gb28181.sip.utils.SipUtil;
import gov.nist.javax.sip.header.Authorization;
import gov.nist.javax.sip.message.SIPRequest;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import javax.sip.header.WWWAuthenticateHeader;
import javax.sip.message.Request;
import javax.sip.message.Response;
@Slf4j
@Data
@SuperBuilder
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class RegisterResponseBuilder extends RegisterBuilder {
/**
* 不做任何校验 即无密码时 使用的认证响应 (如果请求的method错误 依然返回 401 认证失败)
* @param request 请求
*/
public Response createPassedAuthorzatioinResponse(Request request){
SIPRequest sipRequest = (SIPRequest) request;
if(!StringUtils.equalsIgnoreCase(sipRequest.getMethod(), getMethod())){
return SipBuilder.addHeaders(
SipResponseBuilder.createResponse(Response.UNAUTHORIZED, request),
sipRequest.getContactHeader());
}
return SipBuilder.addHeaders(
SipResponseBuilder.createResponse(Response.OK, request),
sipRequest.getContactHeader(),
sipRequest.getExpires());
}
public Response createAuthorzatioinResponse(Request request, String password){
SIPRequest sipRequest = (SIPRequest) request;
Authorization authorization = sipRequest.getAuthorization();
if(authorization == null){
String realm = SipUtil.nanoId();
WWWAuthenticateHeader wwwAuthenticateHeader = DigestAuthenticationHelper.generateChallenge(realm);
return SipBuilder.addHeaders(
SipResponseBuilder.createResponse(Response.UNAUTHORIZED, request),
sipRequest.getContactHeader(),
wwwAuthenticateHeader);
}
boolean passed = DigestAuthenticationHelper.doAuthenticatePlainTextPassword(request,password);
if(!passed){
sipRequest.removeHeader(Authorization.NAME);
return createAuthorzatioinResponse(request, password);
}
return SipBuilder.addHeaders(
SipResponseBuilder.createResponse(Response.OK, request),
sipRequest.getContactHeader(),
sipRequest.getExpires());
}
}

View File

@ -1,52 +0,0 @@
package cn.skcks.docking.gb28181.sip.request;
import cn.skcks.docking.gb28181.sip.generic.SipBuilder;
import cn.skcks.docking.gb28181.sip.generic.SipRequestBuilder;
import cn.skcks.docking.gb28181.sip.utils.DigestAuthenticationHelper;
import cn.skcks.docking.gb28181.sip.utils.SipUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import javax.sip.address.Address;
import javax.sip.address.SipURI;
import javax.sip.header.AuthorizationHeader;
import javax.sip.header.WWWAuthenticateHeader;
import javax.sip.message.Request;
@AllArgsConstructor
@Slf4j
public class RegisterRequestBuilder {
private static final String method = Request.REGISTER;
private String localIp;
private int localPort;
private String localId;
private String targetIp;
private int targetPort;
private String targetId;
private String transport;
public Request createNoAuthorizationRequest(String callId, int expires) {
String local = SipBuilder.createHostAddress(localIp, localPort);
Address localAddress = SipBuilder.createAddress(SipBuilder.createSipURI(localId, local));
String target = SipBuilder.createHostAddress(targetIp, targetPort);
SipURI targetUri = SipBuilder.createSipURI(targetId, target);
Request request = SipRequestBuilder.createRequest(targetUri, method,
SipBuilder.createCallIdHeader(callId),
SipBuilder.createCSeqHeader(1L, method),
SipBuilder.createFromHeader(localAddress, SipUtil.generateFromTag()),
SipBuilder.createToHeader(localAddress),
SipBuilder.createViaHeaders(targetIp, targetPort, transport, SipUtil.generateViaTag()),
SipBuilder.createMaxForwardsHeader(70));
request.addHeader(SipBuilder.createExpiresHeader(expires));
return request;
}
public Request createNoAuthorizationRequest(String callId, int expires, String id, String passwd, WWWAuthenticateHeader wwwAuthenticateHeader) {
Request request = createNoAuthorizationRequest(callId, expires);
AuthorizationHeader authorization = DigestAuthenticationHelper.createAuthorization(method, targetIp, targetPort, targetId, id, passwd, wwwAuthenticateHeader);
request.addHeader(authorization);
return request;
}
}

View File

@ -6,10 +6,16 @@ import cn.skcks.docking.gb28181.sip.header.XGBVerHeader;
import cn.skcks.docking.gb28181.sip.header.impl.XGBVerHeaderImpl;
import cn.skcks.docking.gb28181.sip.generic.SipRequestBuilder;
import cn.skcks.docking.gb28181.sip.generic.SipResponseBuilder;
import cn.skcks.docking.gb28181.sip.parser.GbStringMsgParserFactory;
import cn.skcks.docking.gb28181.sip.property.DefaultProperties;
import cn.skcks.docking.gb28181.sip.utils.SipUtil;
import gov.nist.javax.sip.SipStackImpl;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import javax.sip.ListeningPoint;
import javax.sip.SipProvider;
import javax.sip.address.Address;
import javax.sip.address.SipURI;
import javax.sip.header.*;
@ -20,6 +26,24 @@ import java.util.List;
@Slf4j
public class SipTest {
@Test
@SneakyThrows
public void stackTest(){
// 创建 sip
SipStackImpl sipStack = (SipStackImpl) SipBuilder.getSipFactory()
.createSipStack(DefaultProperties.getProperties(
SipUtil.UserAgent,
"cn.skcks.docking.gb28181.sip.logger.StackLoggerImpl",
"cn.skcks.docking.gb28181.sip.logger.ServerLoggerImpl"));
sipStack.setMessageParserFactory(new GbStringMsgParserFactory());
ListeningPoint listeningPoint = sipStack.createListeningPoint("127.0.0.1", 5060, ListeningPoint.UDP);
SipProvider sipProvider = sipStack.createSipProvider(listeningPoint);
// 各种操作...
Thread.sleep(1000);
// 关闭 sip
sipStack.deleteSipProvider(sipProvider);
sipStack.deleteListeningPoint(listeningPoint);
}
@Test
public void test() {
SipUtil.setUserAgent("GB28181-Docking-Platform Beta");

View File

@ -1,19 +1,17 @@
package cn.skcks.docking.gb28181.sip.process;
import cn.skcks.docking.gb28181.sip.generic.SipBuilder;
import cn.skcks.docking.gb28181.sip.parser.GbStringMsgParserFactory;
import cn.skcks.docking.gb28181.sip.property.DefaultProperties;
import cn.skcks.docking.gb28181.sip.request.RegisterRequestBuilder;
import cn.skcks.docking.gb28181.sip.utils.SipUtil;
import gov.nist.javax.sip.SipStackImpl;
import cn.hutool.core.util.IdUtil;
import cn.skcks.docking.gb28181.sip.method.register.request.RegisterRequestBuilder;
import cn.skcks.docking.gb28181.sip.method.register.response.RegisterResponseBuilder;
import gov.nist.javax.sip.message.SIPResponse;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
import javax.sip.ListeningPoint;
import javax.sip.SipProvider;
import javax.sip.header.UserAgentHeader;
import javax.sip.header.WWWAuthenticateHeader;
import javax.sip.message.Request;
import javax.sip.message.Response;
@Slf4j
public class RequestTest {
@ -27,25 +25,47 @@ public class RequestTest {
@Test
@SneakyThrows
void test(){
SipUtil.setUserAgentVersion("0.1.0");
UserAgentHeader userAgentHeader = SipBuilder.userAgentHeader;
log.info("\n{}",userAgentHeader);
void test() {
String callId = IdUtil.fastSimpleUUID();
RegisterRequestBuilder registerRequestBuilder = RegisterRequestBuilder.builder()
.localIp(localIp)
.localPort(localPort)
.localId(localId)
.targetIp(remoteIp)
.targetPort(remotePort)
.targetId(remoteId)
.transport(ListeningPoint.UDP)
.build();
SipStackImpl sipStack = (SipStackImpl) SipBuilder.getSipFactory()
.createSipStack(DefaultProperties.getProperties(
SipUtil.UserAgent,
"cn.skcks.docking.gb28181.sip.logger.StackLoggerImpl",
"cn.skcks.docking.gb28181.sip.logger.ServerLoggerImpl"));
sipStack.setMessageParserFactory(new GbStringMsgParserFactory());
ListeningPoint listeningPoint = sipStack.createListeningPoint("127.0.0.1", 5060, ListeningPoint.UDP);
SipProvider sipProvider = sipStack.createSipProvider(listeningPoint);
String callId = sipProvider.getNewCallId().getCallId();
RegisterResponseBuilder registerResponseBuilder = RegisterResponseBuilder.builder()
.localIp(remoteIp)
.localPort(remotePort)
.localId(remoteId)
.targetIp(localIp)
.targetPort(localPort)
.targetId(localId)
.transport(ListeningPoint.UDP)
.build();
RegisterRequestBuilder registerRequestBuilder = new RegisterRequestBuilder(localIp, localPort, localId, remoteIp, remotePort, remoteId, ListeningPoint.UDP);
log.info("无密码的认证");
Request noAuthorizationRequest = registerRequestBuilder.createNoAuthorizationRequest(callId, 3600);
log.info("\n{}",noAuthorizationRequest);
sipStack.deleteSipProvider(sipProvider);
sipStack.deleteListeningPoint(listeningPoint);
log.info("\n{}", noAuthorizationRequest);
// 服务端不设置无密码直接通过
Response passedAuthorzatioinResponse = registerResponseBuilder.createPassedAuthorzatioinResponse(noAuthorizationRequest);
log.info("\n{}", passedAuthorzatioinResponse);
log.info("有密码的认证");
Response authorzatioinResponse = registerResponseBuilder.createAuthorzatioinResponse(noAuthorizationRequest, "123456");
log.info("\n{}", noAuthorizationRequest);
// 401 响应
log.info("\n{}", authorzatioinResponse);
SIPResponse sipResponse = (SIPResponse)authorzatioinResponse;
WWWAuthenticateHeader wwwAuthenticateHeader = (WWWAuthenticateHeader)sipResponse.getHeader(WWWAuthenticateHeader.NAME);
// 重新发起带有认证信息的请求
Request authorizationRequest = registerRequestBuilder.createAuthorizationRequest(callId, 3600, localId, "123456", wwwAuthenticateHeader);
log.info("\n{}", authorizationRequest);
authorzatioinResponse = registerResponseBuilder.createAuthorzatioinResponse(authorizationRequest, "123456");
// 注册成功
log.info("\n{}", authorzatioinResponse);
}
}