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 | 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 | 89 | } |
| 90 | 90 | |
| 91 | 91 | // 未携带授权头或者密码错误 回复401 |
| 92 | - if (authorhead == null || !passwordCorrect) { | |
| 92 | + if (authorhead == null ) { | |
| 93 | 93 | |
| 94 | 94 | if (authorhead == null) { |
| 95 | 95 | logger.info("[{}] 未携带授权头 回复401", requestAddress); |
| ... | ... | @@ -98,65 +98,71 @@ public class RegisterRequestProcessor extends SIPRequestAbstractProcessor { |
| 98 | 98 | } |
| 99 | 99 | response = getMessageFactory().createResponse(Response.UNAUTHORIZED, request); |
| 100 | 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 | 166 | getServerTransaction(evt).sendResponse(response); |
| 161 | 167 | // 注册成功 |
| 162 | 168 | // 保存到redis | ... | ... |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java
| ... | ... | @@ -4,7 +4,6 @@ import com.alibaba.fastjson.JSON; |
| 4 | 4 | import com.alibaba.fastjson.JSONArray; |
| 5 | 5 | import com.alibaba.fastjson.JSONObject; |
| 6 | 6 | import com.genersoft.iot.vmp.conf.MediaConfig; |
| 7 | -import com.genersoft.iot.vmp.conf.SipConfig; | |
| 8 | 7 | import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; |
| 9 | 8 | import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
| 10 | 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 | 41 | |
| 42 | 42 | private String streamIp; |
| 43 | 43 | |
| 44 | - private long updateTime; | |
| 44 | + private String updateTime; | |
| 45 | 45 | |
| 46 | 46 | @JSONField(name = "hls.fileBufSize") |
| 47 | 47 | private String hlsFileBufSize; |
| ... | ... | @@ -732,11 +732,11 @@ public class ZLMServerConfig { |
| 732 | 732 | this.shellPhell = shellPhell; |
| 733 | 733 | } |
| 734 | 734 | |
| 735 | - public long getUpdateTime() { | |
| 735 | + public String getUpdateTime() { | |
| 736 | 736 | return updateTime; |
| 737 | 737 | } |
| 738 | 738 | |
| 739 | - public void setUpdateTime(long updateTime) { | |
| 739 | + public void setUpdateTime(String updateTime) { | |
| 740 | 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 | 24 | |
| 25 | 25 | @Update(value = {" <script>" + |
| 26 | 26 | "UPDATE device_channel " + |
| 27 | - "SET updateTime=datetime('now','localtime'))" + | |
| 27 | + "SET updateTime=datetime('now','localtime')" + | |
| 28 | 28 | "<if test=\"name != null\">, name='${name}'</if>" + |
| 29 | 29 | "<if test=\"manufacture != null\">, manufacture='${manufacture}'</if>" + |
| 30 | 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 | 10 | import org.springframework.beans.factory.annotation.Autowired; |
| 11 | 11 | import org.springframework.stereotype.Component; |
| 12 | 12 | |
| 13 | +import java.text.SimpleDateFormat; | |
| 13 | 14 | import java.util.*; |
| 14 | 15 | |
| 15 | 16 | @SuppressWarnings("rawtypes") |
| ... | ... | @@ -22,6 +23,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { |
| 22 | 23 | @Autowired |
| 23 | 24 | private DeviceChannelMapper deviceChannelMapper; |
| 24 | 25 | |
| 26 | + private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | |
| 25 | 27 | |
| 26 | 28 | /** |
| 27 | 29 | * 开始播放时将流存入redis |
| ... | ... | @@ -91,7 +93,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { |
| 91 | 93 | */ |
| 92 | 94 | @Override |
| 93 | 95 | public boolean updateMediaInfo(ZLMServerConfig ZLMServerConfig) { |
| 94 | - ZLMServerConfig.setUpdateTime(System.currentTimeMillis()); | |
| 96 | + ZLMServerConfig.setUpdateTime(format.format(new Date(System.currentTimeMillis()))); | |
| 95 | 97 | return redis.set(VideoManagerConstants.MEDIA_SERVER_PREFIX, ZLMServerConfig); |
| 96 | 98 | } |
| 97 | 99 | ... | ... |