Commit abd569d79a346d9066c4b239dbc452861b26a6cb
1 parent
57b562d6
添加注册失败时回复403避免陷入401循环
Showing
6 changed files
with
124 additions
and
62 deletions
src/main/java/com/genersoft/iot/vmp/gb28181/auth/DigestServerAuthenticationHelper.java
| @@ -241,4 +241,59 @@ public class DigestServerAuthenticationHelper { | @@ -241,4 +241,59 @@ public class DigestServerAuthenticationHelper { | ||
| 241 | return mdString.equals(response); | 241 | return mdString.equals(response); |
| 242 | 242 | ||
| 243 | } | 243 | } |
| 244 | + | ||
| 245 | + public static void main(String[] args) throws NoSuchAlgorithmException { | ||
| 246 | + String realm = "4401000000"; | ||
| 247 | + String username = "44010000001110008008"; | ||
| 248 | + | ||
| 249 | + | ||
| 250 | + String nonce = "0074b397f86fc263b1b7f9eb72553267"; | ||
| 251 | + String uri = "sip:44010000002000000001@4401000000"; | ||
| 252 | + // qop 保护质量 包含auth(默认的)和auth-int(增加了报文完整性检测)两种策略 | ||
| 253 | + String qop = null; | ||
| 254 | + | ||
| 255 | + // 客户端随机数,这是一个不透明的字符串值,由客户端提供,并且客户端和服务器都会使用,以避免用明文文本。 | ||
| 256 | + // 这使得双方都可以查验对方的身份,并对消息的完整性提供一些保护 | ||
| 257 | + //String cNonce = authHeader.getCNonce(); | ||
| 258 | + | ||
| 259 | + // nonce计数器,是一个16进制的数值,表示同一nonce下客户端发送出请求的数量 | ||
| 260 | + int nc = -1; | ||
| 261 | + String ncStr = new DecimalFormat("00000000").format(nc); | ||
| 262 | +// String ncStr = new DecimalFormat("00000000").format(Integer.parseInt(nc + "", 16)); | ||
| 263 | + MessageDigest messageDigest = MessageDigest.getInstance(DEFAULT_ALGORITHM); | ||
| 264 | + String A1 = username + ":" + realm + ":" + "crservice@123"; | ||
| 265 | + String A2 = "REGISTER" + ":" + uri.toString(); | ||
| 266 | + byte mdbytes[] = messageDigest.digest(A1.getBytes()); | ||
| 267 | + String HA1 = toHexString(mdbytes); | ||
| 268 | + System.out.println("A1: " + A1); | ||
| 269 | + System.out.println("A2: " + A2); | ||
| 270 | + | ||
| 271 | + mdbytes = messageDigest.digest(A2.getBytes()); | ||
| 272 | + String HA2 = toHexString(mdbytes); | ||
| 273 | + System.out.println("HA1: " + HA1); | ||
| 274 | + System.out.println("HA2: " + HA2); | ||
| 275 | + String cnonce = null; | ||
| 276 | + System.out.println("nonce: " + nonce); | ||
| 277 | + System.out.println("nc: " + ncStr); | ||
| 278 | + System.out.println("cnonce: " + cnonce); | ||
| 279 | + System.out.println("qop: " + qop); | ||
| 280 | + String KD = HA1 + ":" + nonce; | ||
| 281 | + | ||
| 282 | + if (qop != null && qop.equals("auth") ) { | ||
| 283 | + if (nc != -1) { | ||
| 284 | + KD += ":" + ncStr; | ||
| 285 | + } | ||
| 286 | + if (cnonce != null) { | ||
| 287 | + KD += ":" + cnonce; | ||
| 288 | + } | ||
| 289 | + KD += ":" + qop; | ||
| 290 | + } | ||
| 291 | + KD += ":" + HA2; | ||
| 292 | + System.out.println("KD: " + KD); | ||
| 293 | + mdbytes = messageDigest.digest(KD.getBytes()); | ||
| 294 | + String mdString = toHexString(mdbytes); | ||
| 295 | + System.out.println("mdString: " + mdString); | ||
| 296 | + String response = "fdb1608a7a3b96f0598f40b8ba78d6a9"; | ||
| 297 | + System.out.println("response: " + response); | ||
| 298 | + } | ||
| 244 | } | 299 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/RegisterRequestProcessor.java
| @@ -89,7 +89,7 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor { | @@ -89,7 +89,7 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor { | ||
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | // 未携带授权头或者密码错误 回复401 | 91 | // 未携带授权头或者密码错误 回复401 |
| 92 | - if (authorhead == null || !passwordCorrect) { | 92 | + if (authorhead == null ) { |
| 93 | 93 | ||
| 94 | if (authorhead == null) { | 94 | if (authorhead == null) { |
| 95 | logger.info("[{}] 未携带授权头 回复401", requestAddress); | 95 | logger.info("[{}] 未携带授权头 回复401", requestAddress); |
| @@ -98,65 +98,71 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor { | @@ -98,65 +98,71 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor { | ||
| 98 | } | 98 | } |
| 99 | response = getMessageFactory().createResponse(Response.UNAUTHORIZED, request); | 99 | response = getMessageFactory().createResponse(Response.UNAUTHORIZED, request); |
| 100 | new DigestServerAuthenticationHelper().generateChallenge(getHeaderFactory(), response, sipConfig.getSipDomain()); | 100 | new DigestServerAuthenticationHelper().generateChallenge(getHeaderFactory(), response, sipConfig.getSipDomain()); |
| 101 | - } | ||
| 102 | - // 携带授权头并且密码正确 | ||
| 103 | - else if (passwordCorrect) { | ||
| 104 | - response = getMessageFactory().createResponse(Response.OK, request); | ||
| 105 | - // 添加date头 | ||
| 106 | - SIPDateHeader dateHeader = new SIPDateHeader(); | ||
| 107 | - // 使用自己修改的 | ||
| 108 | - WvpSipDate wvpSipDate = new WvpSipDate(Calendar.getInstance(Locale.ENGLISH).getTimeInMillis()); | ||
| 109 | - dateHeader.setDate(wvpSipDate); | ||
| 110 | - response.addHeader(dateHeader); | ||
| 111 | - | ||
| 112 | - ExpiresHeader expiresHeader = (ExpiresHeader) request.getHeader(Expires.NAME); | ||
| 113 | - if (expiresHeader == null) { | ||
| 114 | - response = getMessageFactory().createResponse(Response.BAD_REQUEST, request); | ||
| 115 | - getServerTransaction(evt).sendResponse(response); | ||
| 116 | - return; | ||
| 117 | - } | ||
| 118 | - // 添加Contact头 | ||
| 119 | - response.addHeader(request.getHeader(ContactHeader.NAME)); | ||
| 120 | - // 添加Expires头 | ||
| 121 | - response.addHeader(request.getExpires()); | ||
| 122 | - | ||
| 123 | - // 获取到通信地址等信息 | ||
| 124 | - ViaHeader viaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); | ||
| 125 | - String received = viaHeader.getReceived(); | ||
| 126 | - int rPort = viaHeader.getRPort(); | ||
| 127 | - // 解析本地地址替代 | ||
| 128 | - if (StringUtils.isEmpty(received) || rPort == -1) { | ||
| 129 | - received = viaHeader.getHost(); | ||
| 130 | - rPort = viaHeader.getPort(); | ||
| 131 | - } | ||
| 132 | - // | 101 | + }else { |
| 102 | + if (!passwordCorrect){ | ||
| 103 | + // 注册失败 | ||
| 104 | + response = getMessageFactory().createResponse(Response.FORBIDDEN, request); | ||
| 105 | + response.setReasonPhrase("wrong password"); | ||
| 106 | + }else { | ||
| 107 | + // 携带授权头并且密码正确 | ||
| 108 | + response = getMessageFactory().createResponse(Response.OK, request); | ||
| 109 | + // 添加date头 | ||
| 110 | + SIPDateHeader dateHeader = new SIPDateHeader(); | ||
| 111 | + // 使用自己修改的 | ||
| 112 | + WvpSipDate wvpSipDate = new WvpSipDate(Calendar.getInstance(Locale.ENGLISH).getTimeInMillis()); | ||
| 113 | + dateHeader.setDate(wvpSipDate); | ||
| 114 | + response.addHeader(dateHeader); | ||
| 115 | + | ||
| 116 | + ExpiresHeader expiresHeader = (ExpiresHeader) request.getHeader(Expires.NAME); | ||
| 117 | + if (expiresHeader == null) { | ||
| 118 | + response = getMessageFactory().createResponse(Response.BAD_REQUEST, request); | ||
| 119 | + getServerTransaction(evt).sendResponse(response); | ||
| 120 | + return; | ||
| 121 | + } | ||
| 122 | + // 添加Contact头 | ||
| 123 | + response.addHeader(request.getHeader(ContactHeader.NAME)); | ||
| 124 | + // 添加Expires头 | ||
| 125 | + response.addHeader(request.getExpires()); | ||
| 126 | + | ||
| 127 | + // 获取到通信地址等信息 | ||
| 128 | + ViaHeader viaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); | ||
| 129 | + String received = viaHeader.getReceived(); | ||
| 130 | + int rPort = viaHeader.getRPort(); | ||
| 131 | + // 解析本地地址替代 | ||
| 132 | + if (StringUtils.isEmpty(received) || rPort == -1) { | ||
| 133 | + received = viaHeader.getHost(); | ||
| 134 | + rPort = viaHeader.getPort(); | ||
| 135 | + } | ||
| 136 | + // | ||
| 133 | 137 | ||
| 134 | - if (device == null) { | ||
| 135 | - device = new Device(); | ||
| 136 | - device.setStreamMode("UDP"); | ||
| 137 | - device.setDeviceId(deviceId); | ||
| 138 | - } | ||
| 139 | - device.setIp(received); | ||
| 140 | - device.setPort(rPort); | ||
| 141 | - device.setHostAddress(received.concat(":").concat(String.valueOf(rPort))); | ||
| 142 | - // 注销成功 | ||
| 143 | - if (expiresHeader.getExpires() == 0) { | ||
| 144 | - registerFlag = 2; | ||
| 145 | - } | ||
| 146 | - // 注册成功 | ||
| 147 | - else { | ||
| 148 | - device.setExpires(expiresHeader.getExpires()); | ||
| 149 | - registerFlag = 1; | ||
| 150 | - // 判断TCP还是UDP | ||
| 151 | - boolean isTcp = false; | ||
| 152 | - ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); | ||
| 153 | - String transport = reqViaHeader.getTransport(); | ||
| 154 | - if (transport.equals("TCP")) { | ||
| 155 | - isTcp = true; | 138 | + if (device == null) { |
| 139 | + device = new Device(); | ||
| 140 | + device.setStreamMode("UDP"); | ||
| 141 | + device.setDeviceId(deviceId); | ||
| 142 | + } | ||
| 143 | + device.setIp(received); | ||
| 144 | + device.setPort(rPort); | ||
| 145 | + device.setHostAddress(received.concat(":").concat(String.valueOf(rPort))); | ||
| 146 | + // 注销成功 | ||
| 147 | + if (expiresHeader.getExpires() == 0) { | ||
| 148 | + registerFlag = 2; | ||
| 149 | + } | ||
| 150 | + // 注册成功 | ||
| 151 | + else { | ||
| 152 | + device.setExpires(expiresHeader.getExpires()); | ||
| 153 | + registerFlag = 1; | ||
| 154 | + // 判断TCP还是UDP | ||
| 155 | + boolean isTcp = false; | ||
| 156 | + ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); | ||
| 157 | + String transport = reqViaHeader.getTransport(); | ||
| 158 | + if (transport.equals("TCP")) { | ||
| 159 | + isTcp = true; | ||
| 160 | + } | ||
| 161 | + device.setTransport(isTcp ? "TCP" : "UDP"); | ||
| 156 | } | 162 | } |
| 157 | - device.setTransport(isTcp ? "TCP" : "UDP"); | ||
| 158 | } | 163 | } |
| 159 | } | 164 | } |
| 165 | + | ||
| 160 | getServerTransaction(evt).sendResponse(response); | 166 | getServerTransaction(evt).sendResponse(response); |
| 161 | // 注册成功 | 167 | // 注册成功 |
| 162 | // 保存到redis | 168 | // 保存到redis |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java
| @@ -4,7 +4,6 @@ import com.alibaba.fastjson.JSON; | @@ -4,7 +4,6 @@ import com.alibaba.fastjson.JSON; | ||
| 4 | import com.alibaba.fastjson.JSONArray; | 4 | import com.alibaba.fastjson.JSONArray; |
| 5 | import com.alibaba.fastjson.JSONObject; | 5 | import com.alibaba.fastjson.JSONObject; |
| 6 | import com.genersoft.iot.vmp.conf.MediaConfig; | 6 | import com.genersoft.iot.vmp.conf.MediaConfig; |
| 7 | -import com.genersoft.iot.vmp.conf.SipConfig; | ||
| 8 | import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; | 7 | import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; |
| 9 | import com.genersoft.iot.vmp.storager.IVideoManagerStorager; | 8 | import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
| 10 | import com.genersoft.iot.vmp.service.IStreamProxyService; | 9 | import com.genersoft.iot.vmp.service.IStreamProxyService; |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerConfig.java
| @@ -41,7 +41,7 @@ public class ZLMServerConfig { | @@ -41,7 +41,7 @@ public class ZLMServerConfig { | ||
| 41 | 41 | ||
| 42 | private String streamIp; | 42 | private String streamIp; |
| 43 | 43 | ||
| 44 | - private long updateTime; | 44 | + private String updateTime; |
| 45 | 45 | ||
| 46 | @JSONField(name = "hls.fileBufSize") | 46 | @JSONField(name = "hls.fileBufSize") |
| 47 | private String hlsFileBufSize; | 47 | private String hlsFileBufSize; |
| @@ -732,11 +732,11 @@ public class ZLMServerConfig { | @@ -732,11 +732,11 @@ public class ZLMServerConfig { | ||
| 732 | this.shellPhell = shellPhell; | 732 | this.shellPhell = shellPhell; |
| 733 | } | 733 | } |
| 734 | 734 | ||
| 735 | - public long getUpdateTime() { | 735 | + public String getUpdateTime() { |
| 736 | return updateTime; | 736 | return updateTime; |
| 737 | } | 737 | } |
| 738 | 738 | ||
| 739 | - public void setUpdateTime(long updateTime) { | 739 | + public void setUpdateTime(String updateTime) { |
| 740 | this.updateTime = updateTime; | 740 | this.updateTime = updateTime; |
| 741 | } | 741 | } |
| 742 | 742 |
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java
| @@ -24,7 +24,7 @@ public interface DeviceChannelMapper { | @@ -24,7 +24,7 @@ public interface DeviceChannelMapper { | ||
| 24 | 24 | ||
| 25 | @Update(value = {" <script>" + | 25 | @Update(value = {" <script>" + |
| 26 | "UPDATE device_channel " + | 26 | "UPDATE device_channel " + |
| 27 | - "SET updateTime=datetime('now','localtime'))" + | 27 | + "SET updateTime=datetime('now','localtime')" + |
| 28 | "<if test=\"name != null\">, name='${name}'</if>" + | 28 | "<if test=\"name != null\">, name='${name}'</if>" + |
| 29 | "<if test=\"manufacture != null\">, manufacture='${manufacture}'</if>" + | 29 | "<if test=\"manufacture != null\">, manufacture='${manufacture}'</if>" + |
| 30 | "<if test=\"model != null\">, model='${model}'</if>" + | 30 | "<if test=\"model != null\">, model='${model}'</if>" + |
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
| @@ -10,6 +10,7 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil; | @@ -10,6 +10,7 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil; | ||
| 10 | import org.springframework.beans.factory.annotation.Autowired; | 10 | import org.springframework.beans.factory.annotation.Autowired; |
| 11 | import org.springframework.stereotype.Component; | 11 | import org.springframework.stereotype.Component; |
| 12 | 12 | ||
| 13 | +import java.text.SimpleDateFormat; | ||
| 13 | import java.util.*; | 14 | import java.util.*; |
| 14 | 15 | ||
| 15 | @SuppressWarnings("rawtypes") | 16 | @SuppressWarnings("rawtypes") |
| @@ -22,6 +23,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | @@ -22,6 +23,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | ||
| 22 | @Autowired | 23 | @Autowired |
| 23 | private DeviceChannelMapper deviceChannelMapper; | 24 | private DeviceChannelMapper deviceChannelMapper; |
| 24 | 25 | ||
| 26 | + private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | ||
| 25 | 27 | ||
| 26 | /** | 28 | /** |
| 27 | * 开始播放时将流存入redis | 29 | * 开始播放时将流存入redis |
| @@ -91,7 +93,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | @@ -91,7 +93,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | ||
| 91 | */ | 93 | */ |
| 92 | @Override | 94 | @Override |
| 93 | public boolean updateMediaInfo(ZLMServerConfig ZLMServerConfig) { | 95 | public boolean updateMediaInfo(ZLMServerConfig ZLMServerConfig) { |
| 94 | - ZLMServerConfig.setUpdateTime(System.currentTimeMillis()); | 96 | + ZLMServerConfig.setUpdateTime(format.format(new Date(System.currentTimeMillis()))); |
| 95 | return redis.set(VideoManagerConstants.MEDIA_SERVER_PREFIX, ZLMServerConfig); | 97 | return redis.set(VideoManagerConstants.MEDIA_SERVER_PREFIX, ZLMServerConfig); |
| 96 | } | 98 | } |
| 97 | 99 |