一、报文封装类
AbstractPortalMsg.java
Portal协议数据报文封装类
1 package org.yoki.edu.common.protocol.portal.msg; 2 3 import lombok.Data; 4 import lombok.ToString; 5 import org.yoki.edu.common.protocol.portal.msg.attr.MsgAttr; 6 7 import java.util.ArrayList; 8 import java.util.List; 9 10 /** 11 * Portal协议数据报文封装类 12 * 13 * @author Sky$ 14 * @Description: TODO 15 * @date 2017/10/24$ 19:16$ 16 */ 17 @Data 18 @ToString 19 public abstract class AbstractPortalMsg { 20 21 protected int ver; 22 protected int type; 23 protected int papChap = 1; 24 protected int rsvd = 0; 25 protected int serialNo; 26 protected int reqId; 27 protected String userIp; 28 protected int userPort = 0; 29 protected int errCode; 30 protected int attrNum; 31 /** 32 * 属性列表 33 */ 34 protected List<MsgAttr> attrList = new ArrayList<>(); 35 36 /** 37 * 添加属性的方法 38 * 39 * @param attr 40 * @return 41 */ 42 public List<MsgAttr> addMsgAttr(MsgAttr attr) { 43 if (null == attrList) { 44 attrList = new ArrayList<>(); 45 } 46 attrList.add(attr); 47 return attrList; 48 } 49 50 51 /** 52 * 将hander部分的字段转化为16个字节 53 * 54 * @return 55 */ 56 protected byte[] getHander16Bytes() { 57 byte[] b = new byte[16]; 58 b[0] = (byte) (ver & 0xff); 59 b[1] = (byte) (type & 0xff); 60 b[2] = (byte) (papChap & 0xff); 61 b[3] = (byte) (rsvd & 0xff); 62 b[4] = (byte) (serialNo >> 8 & 0xff); 63 b[5] = (byte) (serialNo & 0xff); 64 b[6] = (byte) (reqId >> 8 & 0xff); 65 b[7] = (byte) (reqId & 0xff); 66 byte[] ip = ipv4Address2BinaryArray(userIp); 67 System.arraycopy(ip, 0, b, 8, 4); 68 b[12] = (byte) (userPort >> 8 & 0xff); 69 b[13] = (byte) (userPort & 0xff); 70 b[14] = (byte) (errCode & 0xff); 71 b[15] = (byte) (attrNum & 0xff); 72 return b; 73 } 74 75 /** 76 * 将属性列表转化为字节数组 77 * 78 * @return 79 */ 80 protected byte[] getAttrBytes() { 81 int attrByteNum = 0; 82 if (attrList != null && !attrList.isEmpty()) { 83 for (MsgAttr a : attrList) { 84 attrByteNum += a.getAttrLen(); 85 } 86 } 87 byte[] b = new byte[attrByteNum]; 88 int index = 0; 89 if (attrList != null && !attrList.isEmpty()) { 90 for (MsgAttr a : attrList) { 91 System.arraycopy(a.getByteValues(), 0, b, index, a.getByteValues().length); 92 index += a.getByteValues().length; 93 } 94 } 95 return b; 96 } 97 98 /** 99 * 抽象方法:获取该报文类的字节数组<br> 100 * 抽象出该方法是因为移动Portal和华为Portal协议有些区别<br> 101 * 华为Portal有一个MD5加密字段 102 * 103 * @return 104 */ 105 public abstract byte[] toByteArray(); 106 107 /** 108 * 抽象方法:通过报文字节数组,解析出各个字段值,并赋值<br> 109 * 抽象出该方法是因为移动Portal和华为Portal协议有些区别<br> 110 * 华为Portal有一个MD5加密字段 111 * 112 * @param input Portal协议报文字节数组 113 */ 114 public abstract void parse(byte[] input); 115 116 /** 117 * 通过报文字节数组,解析出header部分的信息,并赋值 118 * 119 * @param input Portal协议报文字节数组 120 */ 121 protected void parseHeader(byte[] input) { 122 this.setVer(input[0]); 123 this.setType(input[1]); 124 this.setPapChap(input[2]); 125 this.setRsvd(input[3]); 126 127 this.setSerialNo(((0xff & input[4]) << 8) | (0xff & input[5])); 128 this.setReqId(((0xff & input[6]) << 8) | (0xff & input[7])); 129 130 this.setUserIp((input[8] & 0xff) + "." + (input[9] & 0xff) + "." + (input[10] & 0xff) + "." + (input[11] & 0xff)); 131 this.setUserPort(((0xff & input[12]) << 8) | (0xff & input[13])); 132 133 this.setErrCode(0xff & input[14]); 134 this.setAttrNum(0xff & input[15]); 135 } 136 137 /** 138 * 通过报文字节数组,解析出attr部分的信息,并赋值 139 * 140 * @param attrBytes attr数组的字节数组 141 * @param attrNum attr的个数 142 */ 143 protected void parseAttr(byte[] attrBytes, int attrNum) { 144 List<MsgAttr> attrList = new ArrayList<MsgAttr>(); 145 int count = attrNum; 146 if (count > 0) { 147 int t = 0; 148 for (int i = 0; i < count; i++) { 149 int attrType = attrBytes[t]; 150 int attrLen = attrBytes[t + 1]; 151 byte[] d = new byte[attrLen - 2]; 152 System.arraycopy(attrBytes, t + 2, d, 0, attrLen - 2); 153 MsgAttr c = new MsgAttr(attrType, new String(d)); 154 attrList.add(c); 155 t += c.getAttrLen(); 156 } 157 } 158 this.setAttrList(attrList); 159 } 160 161 /** 162 * IP地址转换工具方法,将IP字符串转换为字节数组 163 * 164 * @param ipAdd 165 * @return 166 */ 167 protected byte[] ipv4Address2BinaryArray(String ipAdd) { 168 byte[] binIP = new byte[4]; 169 String[] strs = ipAdd.split("\\."); 170 for (int i = 0; i < strs.length; i++) { 171 binIP[i] = (byte) Integer.parseInt(strs[i]); 172 } 173 return binIP; 174 } 175 176 177 }
PortalV1Msg.java
移动Portal协议数据报文封装类
1 package org.yoki.edu.common.protocol.portal.msg; 2 3 import lombok.NoArgsConstructor; 4 import org.yoki.edu.common.protocol.portal.msg.attr.MsgAttr; 5 6 import java.util.List; 7 8 /** 9 * 移动Portal协议数据报文封装类 10 * 11 * @author Sky$ 12 * @Description: TODO 13 * @date 2017/10/25$ 14:52$ 14 */ 15 @NoArgsConstructor 16 public class PortalV1Msg extends AbstractPortalMsg { 17 18 public PortalV1Msg(int ver, int type, int serialNo, int reqId, String userIp, int errCode, int attrNum, List<MsgAttr> attr) { 19 super(); 20 this.ver = ver; 21 this.type = type; 22 this.serialNo = serialNo; 23 this.reqId = reqId; 24 this.userIp = userIp; 25 this.errCode = errCode; 26 this.attrNum = attrNum; 27 this.attrList = attr; 28 } 29 30 public PortalV1Msg(int ver, int type, int papChap, int rsvd, int serialNo, int reqId, String userIp, int userPort, 31 int errCode, int attrNum, List<MsgAttr> attr) { 32 super(); 33 this.ver = ver; 34 this.type = type; 35 this.papChap = papChap; 36 this.rsvd = rsvd; 37 this.serialNo = serialNo; 38 this.reqId = reqId; 39 this.userIp = userIp; 40 this.userPort = userPort; 41 this.errCode = errCode; 42 this.attrNum = attrNum; 43 this.attrList = attr; 44 } 45 46 47 @Override 48 public byte[] toByteArray() { 49 byte[] headerBytes = getHander16Bytes(); 50 byte[] attrBytes = getAttrBytes(); 51 byte[] b = new byte[headerBytes.length + attrBytes.length]; 52 if (null != headerBytes && headerBytes.length > 0) { 53 System.arraycopy(headerBytes, 0, b, 0, headerBytes.length); 54 } 55 b[15] = (byte) this.attrList.size(); 56 if (null != attrBytes && attrBytes.length > 0) { 57 System.arraycopy(attrBytes, 0, b, 16, attrBytes.length); 58 } 59 return b; 60 } 61 62 63 @Override 64 public void parse(byte[] input) { 65 66 if (null != input && input.length >= 16) { 67 byte[] headerBytes = new byte[16]; 68 System.arraycopy(input, 0, headerBytes, 0, headerBytes.length); 69 this.parseHeader(headerBytes); 70 71 int attrNum = input[15]; 72 byte[] attrBytes = new byte[input.length - 16]; 73 System.arraycopy(input, 16, attrBytes, 0, attrBytes.length); 74 parseAttr(attrBytes, attrNum); 75 } 76 77 } 78 79 }
MsgAttr.java
Portal数据报文Attr字段封装父类
1 package org.yoki.edu.common.protocol.portal.msg.attr; 2 3 import lombok.Data; 4 import lombok.Getter; 5 import lombok.NoArgsConstructor; 6 7 import java.util.Arrays; 8 9 /** 10 * Portal数据报文Attr字段封装父类 11 * 12 * @author Sky$ 13 * @Description: TODO 14 * @date 2017/10/24$ 20:44$ 15 */ 16 @Data 17 public class MsgAttr { 18 19 private int attrType; 20 private int attrLen; 21 private String attrValue; 22 private byte[] byteValues; 23 24 protected MsgAttr() { 25 26 } 27 28 public MsgAttr(int attrType, String attrValue) { 29 this.attrType = attrType; 30 this.attrLen = 2 + attrValue.getBytes().length; 31 this.attrValue = attrValue; 32 33 byteValues = new byte[attrLen]; 34 byteValues[0] = (byte) attrType; 35 byteValues[1] = (byte) attrLen; 36 System.arraycopy(attrValue.getBytes(), 0, byteValues, 2, attrValue.getBytes().length); 37 } 38 39 }
UserNameMsgAttr.java
1 package org.yoki.edu.common.protocol.portal.msg.attr; 2 3 /** 4 * @author Sky$ 5 * @Description: TODO 6 * @date 2017/10/29$ 15:05$ 7 */ 8 public class UserNameMsgAttr extends MsgAttr { 9 10 public UserNameMsgAttr(String userName){ 11 super(0x01 , userName) ; 12 } 13 14 }
PasswordMsgAttr.java
1 package org.yoki.edu.common.protocol.portal.msg.attr; 2 3 /** 4 * @author Sky$ 5 * @Description: TODO 6 * @date 2017/10/29$ 15:08$ 7 */ 8 public class PasswordMsgAttr extends MsgAttr { 9 10 public PasswordMsgAttr(String password){ 11 super(0x02 , password) ; 12 } 13 14 }
ChallengeMsgAttr.java
1 package org.yoki.edu.common.protocol.portal.msg.attr; 2 3 /** 4 * @author Sky$ 5 * @Description: TODO 6 * @date 2017/10/29$ 15:09$ 7 */ 8 public class ChallengeMsgAttr extends MsgAttr { 9 10 public ChallengeMsgAttr(String challenge){ 11 super(0x03 , challenge) ; 12 } 13 14 }
ChapPasswordMsgAttr.java
1 package org.yoki.edu.common.protocol.portal.msg.attr; 2 3 /** 4 * @author Sky$ 5 * @Description: TODO 6 * @date 2017/10/29$ 15:09$ 7 */ 8 public class ChapPasswordMsgAttr extends MsgAttr { 9 10 public ChapPasswordMsgAttr(String chapPassword){ 11 super(0x04 , chapPassword) ; 12 } 13 14 }
二、工具类
ChapEncryptUtils.java
Chap加密工具类
1 package org.yoki.edu.common.protocol.portal.utils; 2 3 import org.yoki.edu.common.utils.encrypt.EncryptUtils; 4 5 /** 6 * Chap加密 7 * 8 * @author Sky$ 9 * @Description: TODO 10 * @date 2017/10/27$ 17:20$ 11 */ 12 public class ChapEncryptUtils { 13 14 public static byte[] encryptChap(int reqId, String challenge, String pwd) { 15 byte[] chapPwd = encryptChap(reqId, challenge.getBytes(), pwd.getBytes()); 16 return chapPwd; 17 } 18 19 public static byte[] encryptChap(int reqId, byte[] challenge, byte[] pwd) { 20 /** 21 * Chap_Password(Chap密码)的生成: 22 * Chap_Password的生成遵循标准的Radious协议中的Chap_Password 生成方法(参见RFC2865)。 23 * 密码加密使用MD5算法,MD5函数的输入为ChapID + Password +Challenge (reqId有AC生成, ChapID是ReqID的低8位) 24 * 其中,ChapID取reqId的低 8 位,Password的长度不够协议规定的最大长度,其后不需要补零。 25 * Chap_Password = MD5 (ChapID+ Password + Challenge ) 26 */ 27 byte[] buf = new byte[1 + pwd.length + challenge.length]; 28 buf[0] = (byte) (reqId & 0xff); 29 System.arraycopy(pwd, 0, buf, 1, pwd.length); 30 System.arraycopy(challenge, 0, buf, 1 + pwd.length, challenge.length); 31 byte[] chapPwd = EncryptUtils.encryptMD5Bytes(buf); 32 return chapPwd; 33 } 34 35 }
三、Portal协议工具类
PortalV1ChapMsgBuilder.java
CHAP方式Portal报文生产工具类
1 package org.yoki.edu.common.protocol.portal.v1.builder; 2 3 import org.yoki.edu.common.protocol.portal.msg.attr.UserNameMsgAttr; 4 import org.yoki.edu.common.protocol.portal.utils.ChapEncryptUtils; 5 import org.yoki.edu.common.protocol.portal.msg.PortalV1Msg; 6 import org.yoki.edu.common.protocol.portal.msg.attr.ChapPasswordMsgAttr; 7 8 /** 9 * CHAP方式Portal报文生产工具类 10 * 11 * @author Sky$ 12 * @Description: TODO 13 * @date 2017/10/29$ 14:37$ 14 */ 15 public class PortalV1ChapMsgBuilder { 16 17 /** 18 * 生成Chanllenge请求报文 19 * 20 * @param serialNo 21 * @param userIp 用户IP 22 * @return 23 */ 24 public PortalV1Msg buildReqChallengeMsg(int serialNo, String userIp) { 25 PortalV1Msg msg = buildV1ChapMsg(); 26 msg.setType(1); 27 msg.setReqId(0); 28 msg.setSerialNo(serialNo); 29 msg.setUserIp(userIp); 30 msg.setAttrNum(0); 31 return msg; 32 } 33 34 /** 35 * 生成认证请求报文 36 * 37 * @param reqId 38 * @param serialNo 39 * @param userIp 40 * @param userName 41 * @param password 42 * @param challenge 43 * @return 44 */ 45 public PortalV1Msg buildReqAuthMsg(int reqId, int serialNo, String userIp, String userName, String password, String challenge) { 46 PortalV1Msg msg = buildV1ChapMsg(); 47 msg.setType(3); 48 msg.setSerialNo(serialNo); 49 msg.setReqId(reqId); 50 msg.setUserIp(userIp); 51 msg.setAttrNum(2); 52 UserNameMsgAttr userNameMsgAttr = new UserNameMsgAttr(userName); 53 byte[] chapPassworldBytes = ChapEncryptUtils.encryptChap(reqId, challenge, password); 54 ChapPasswordMsgAttr chapPasswordMsgAttr = new ChapPasswordMsgAttr(new String(chapPassworldBytes)); 55 msg.addMsgAttr(userNameMsgAttr).add(chapPasswordMsgAttr); 56 return msg; 57 } 58 59 /** 60 * 生成下线请求报文 61 * 62 * @param reqId 63 * @param serialNo 64 * @param userIp 65 * @return 66 */ 67 public PortalV1Msg buildReqLogoutMsg(int reqId, int serialNo, String userIp) { 68 PortalV1Msg msg = buildV1ChapMsg(); 69 msg.setType(5); 70 msg.setSerialNo(serialNo); 71 msg.setReqId(reqId); 72 msg.setUserIp(userIp); 73 msg.setAttrNum(0); 74 return msg; 75 } 76 77 /** 78 * 生成认证接收响应报文 79 * 80 * @param reqId 81 * @param serialNo 82 * @param userIp 83 * @return 84 */ 85 public PortalV1Msg buildAffAckAuthMsg(int reqId, int serialNo, String userIp) { 86 PortalV1Msg msg = buildV1ChapMsg(); 87 msg.setType(7); 88 msg.setSerialNo(serialNo); 89 msg.setReqId(reqId); 90 msg.setUserIp(userIp); 91 msg.setAttrNum(0); 92 return msg; 93 } 94 95 96 private PortalV1Msg buildV1ChapMsg() { 97 PortalV1Msg msg = new PortalV1Msg(); 98 msg.setVer(1); 99 100 msg.setPapChap(0); 101 msg.setRsvd(0); 102 103 msg.setUserPort(0); 104 msg.setErrCode(0); 105 return msg; 106 } 107 108 109 }
PortalV1PapMsgBuilder.java
PAP方式Portal报文生产工具类
1 package org.yoki.edu.common.protocol.portal.v1.builder; 2 3 import org.yoki.edu.common.protocol.portal.msg.PortalV1Msg; 4 import org.yoki.edu.common.protocol.portal.msg.attr.PasswordMsgAttr; 5 import org.yoki.edu.common.protocol.portal.msg.attr.UserNameMsgAttr; 6 7 /** 8 * PAP方式Portal报文生产工具类 9 * 10 * @author Sky$ 11 * @Description: TODO 12 * @date 2017/10/29$ 14:37$ 13 */ 14 public class PortalV1PapMsgBuilder { 15 16 /** 17 * 生成认证请求报文 18 * 19 * @param serialNo 20 * @param userIp 21 * @param userName 22 * @param password 23 * @return 24 */ 25 public PortalV1Msg buildReqAuthMsg(int serialNo, String userIp, String userName, String password) { 26 PortalV1Msg msg = buildV1PapMsg(); 27 msg.setType(3); 28 msg.setSerialNo(serialNo); 29 30 msg.setUserIp(userIp); 31 msg.setAttrNum(2); 32 UserNameMsgAttr userNameMsgAttr = new UserNameMsgAttr(userName); 33 PasswordMsgAttr passwordMsgAttr = new PasswordMsgAttr(password); 34 msg.addMsgAttr(userNameMsgAttr).add(passwordMsgAttr); 35 return msg; 36 } 37 38 /** 39 * 生成下线请求报文 40 * 41 * @param serialNo 42 * @param userIp 43 * @return 44 */ 45 public PortalV1Msg buildReqLogoutMsg(int serialNo, String userIp) { 46 PortalV1Msg msg = buildV1PapMsg(); 47 msg.setType(5); 48 msg.setSerialNo(serialNo); 49 msg.setUserIp(userIp); 50 msg.setAttrNum(0); 51 return msg; 52 } 53 54 /** 55 * 生成认证接收响应报文 56 * 57 * @param serialNo 58 * @param userIp 59 * @return 60 */ 61 public PortalV1Msg buildAffAckAuthMsg(int serialNo, String userIp) { 62 PortalV1Msg msg = buildV1PapMsg(); 63 msg.setType(7); 64 msg.setSerialNo(serialNo); 65 msg.setUserIp(userIp); 66 msg.setAttrNum(0); 67 return msg; 68 } 69 70 private PortalV1Msg buildV1PapMsg() { 71 PortalV1Msg msg = new PortalV1Msg(); 72 msg.setVer(1); 73 74 msg.setPapChap(1); 75 msg.setRsvd(0); 76 77 msg.setReqId(0); 78 79 msg.setUserPort(0); 80 msg.setErrCode(0); 81 return msg; 82 } 83 84 85 }
PortalV1MsgParser.java
报文解析工具类
1 package org.yoki.edu.common.protocol.portal.v1.parser; 2 3 import org.yoki.edu.common.protocol.portal.exception.PortalException; 4 import org.yoki.edu.common.protocol.portal.exception.enums.PortalErrorStatusEnum; 5 import org.yoki.edu.common.protocol.portal.msg.PortalV1Msg; 6 7 /** 8 * 报文解析工具类 9 * 10 * @author Sky$ 11 * @Description: TODO 12 * @date 2017/10/29$ 15:59$ 13 */ 14 public class PortalV1MsgParser { 15 16 private final int ACK_CHALLENGE = 0X02; 17 private final int ACK_AUTH = 0X04; 18 private final int ACK_LOGOUT = 0X06; 19 20 private final int ERROR_CODE_1 = 1; 21 private final int ERROR_CODE_2 = 2; 22 private final int ERROR_CODE_3 = 3; 23 private final int ERROR_CODE_4 = 4; 24 25 public PortalV1Msg parse(byte[] input) throws PortalException { 26 PortalV1Msg msg = new PortalV1Msg(); 27 msg.parse(input); 28 parse(msg); 29 return msg; 30 } 31 32 public void parse(PortalV1Msg msg) throws PortalException { 33 Integer type = msg.getType(); 34 Integer errorCode = msg.getErrCode(); 35 PortalErrorStatusEnum[] enums = PortalErrorStatusEnum.values(); 36 for (PortalErrorStatusEnum e : enums) { 37 if (e.getErrCode() == errorCode && e.getType() == type) { 38 throw new PortalException(e); 39 } 40 } 41 } 42 43 }
PortalV1PapMsgSender.java
Portal报文发送工具类
内部调用DatagramSocket进行UDP报文发送
1 package org.yoki.edu.common.protocol.portal.v1.sender; 2 3 import lombok.Getter; 4 import lombok.Setter; 5 import org.yoki.edu.common.protocol.portal.v1.builder.PortalV1PapMsgBuilder; 6 import org.yoki.edu.common.protocol.portal.exception.PortalException; 7 import org.yoki.edu.common.protocol.portal.msg.PortalV1Msg; 8 import org.yoki.edu.common.protocol.portal.v1.parser.PortalV1MsgParser; 9 10 import java.io.IOException; 11 import java.net.DatagramPacket; 12 import java.net.DatagramSocket; 13 import java.net.InetAddress; 14 15 /** 16 * Portal报文发送工具类<br> 17 * 内部调用DatagramSocket进行UDP报文发送 18 * 19 * @author Sky$ 20 * @Description: TODO 21 * @date 2017/10/31$ 17:57$ 22 */ 23 public class PortalV1PapMsgSender { 24 25 @Setter 26 @Getter 27 private int timeOut = 5000; 28 29 @Setter 30 @Getter 31 private Integer receiverPort = null; 32 33 /** 34 * REQ_AUTH 0x03 Client----->Server AbstractPortalMsg Server向AC设备发送的请求认证报文 35 * 36 * @param serialNo 37 * @param loginIp 38 * @param loginName 39 * @param password 40 * @param acIp 41 * @param acPort 42 * @return 43 * @throws Exception 44 */ 45 public byte[] sendReqAuth(int serialNo, String loginIp, String loginName, String password, String acIp, int acPort) throws IOException { 46 DatagramSocket dataSocket = null; 47 byte[] ackData = new byte[0]; 48 dataSocket = null; 49 DatagramPacket requestPacket = null; 50 PortalV1PapMsgBuilder builder = new PortalV1PapMsgBuilder(); 51 PortalV1Msg msg = builder.buildReqAuthMsg(serialNo, loginIp, loginName, password); 52 byte[] msgBytes = msg.toByteArray(); 53 // 创建连接 54 if (null != receiverPort) { 55 dataSocket = new DatagramSocket(receiverPort); 56 } else { 57 dataSocket = new DatagramSocket(); 58 } 59 // 创建发送数据包并发送给服务器 60 requestPacket = new DatagramPacket(msgBytes, msgBytes.length, InetAddress.getByName(acIp), acPort); 61 ackData = new byte[1024]; 62 // 接收服务器的数据包 63 DatagramPacket receivePacket = new DatagramPacket(ackData, 32); 64 // 设置请求超时3秒 65 dataSocket.setSoTimeout(timeOut); 66 dataSocket.send(requestPacket); 67 dataSocket.receive(receivePacket); 68 69 if (null != dataSocket) { 70 dataSocket.disconnect(); 71 dataSocket.close(); 72 } 73 return ackData; 74 75 } 76 77 /** 78 * REQ_AUTH 0x03 Client----->Server AbstractPortalMsg Server向AC设备发送的请求认证报文 79 * 80 * @param serialNo 81 * @param loginIp 82 * @param loginName 83 * @param password 84 * @param acIp 85 * @param acPort 86 * @return 87 * @throws Exception 88 */ 89 public PortalV1Msg sendAndParseReqAuth(int serialNo, String loginIp, String loginName, String password, String acIp, int acPort) throws PortalException, IOException { 90 byte[] ackData = sendReqAuth(serialNo, loginIp, loginName, password, acIp, acPort); 91 PortalV1MsgParser msgParser = new PortalV1MsgParser(); 92 PortalV1Msg reciveMsg = msgParser.parse(ackData); 93 reciveMsg.parse(ackData); 94 return reciveMsg; 95 96 } 97 98 /** 99 * AbstractPortalMsg Server对收到的认证成功响应报文的确认报文; 100 * 101 * @param serialNo 102 * @param loginIp 103 * @param acIp 104 * @param acPort 105 * @throws Exception 106 */ 107 public void sendAffAckAuth(int serialNo, String loginIp, String acIp, int acPort) throws IOException { 108 DatagramSocket dataSocket = null; 109 PortalV1PapMsgBuilder builder = new PortalV1PapMsgBuilder(); 110 PortalV1Msg msg = builder.buildAffAckAuthMsg(serialNo, loginIp); 111 byte[] msgBytes = msg.toByteArray(); 112 // 创建连接 113 if (null != receiverPort) { 114 dataSocket = new DatagramSocket(receiverPort); 115 } else { 116 dataSocket = new DatagramSocket(); 117 } 118 // 创建发送数据包并发送给服务器 119 DatagramPacket requestPacket = new DatagramPacket(msgBytes, msgBytes.length, InetAddress.getByName(acIp), acPort); 120 // 接收服务器的数据包 121 dataSocket.send(requestPacket); 122 if (null != dataSocket) { 123 dataSocket.disconnect(); 124 dataSocket.close(); 125 } 126 } 127 128 129 /** 130 * AbstractPortalMsg Server向AC设备发送的请求用户下线报文 131 * 132 * @param serialNo 133 * @param loginIp 134 * @param acIp 135 * @param acPort 136 * @return 137 * @throws Exception 138 */ 139 public byte[] sendReqLogout(int serialNo, String loginIp, String acIp, int acPort) throws IOException { 140 DatagramSocket dataSocket = null; 141 byte[] ackData = new byte[0]; 142 PortalV1PapMsgBuilder builder = new PortalV1PapMsgBuilder(); 143 PortalV1Msg msg = builder.buildReqLogoutMsg(serialNo, loginIp); 144 byte[] msgBytes = msg.toByteArray(); 145 // 创建连接 146 if (null != receiverPort) { 147 dataSocket = new DatagramSocket(receiverPort); 148 } else { 149 dataSocket = new DatagramSocket(); 150 } 151 // 创建发送数据包并发送给服务器 152 DatagramPacket requestPacket = new DatagramPacket(msgBytes, msgBytes.length, InetAddress.getByName(acIp), acPort); 153 ackData = new byte[1024]; 154 // 接收服务器的数据包 155 DatagramPacket receivePacket = new DatagramPacket(ackData, 32); 156 // 设置请求超时3秒 157 dataSocket.setSoTimeout(timeOut); 158 dataSocket.send(requestPacket); 159 dataSocket.receive(receivePacket); 160 if (null != dataSocket) { 161 dataSocket.disconnect(); 162 dataSocket.close(); 163 } 164 return ackData; 165 166 167 } 168 169 /** 170 * AbstractPortalMsg Server向AC设备发送的请求用户下线报文 171 * 172 * @param serialNo 173 * @param loginIp 174 * @param acIp 175 * @param acPort 176 * @return 177 * @throws Exception 178 */ 179 public PortalV1Msg sendAndParseReqLogout(int serialNo, String loginIp, String acIp, int acPort) throws IOException, PortalException { 180 byte[] ackData = sendReqLogout(serialNo, loginIp, acIp, acPort); 181 PortalV1MsgParser msgParser = new PortalV1MsgParser(); 182 PortalV1Msg reciveMsg = msgParser.parse(ackData); 183 reciveMsg.parse(ackData); 184 return reciveMsg; 185 186 } 187 188 }
四、使用示例
1 /** 2 * 用户短信认证 3 * 4 * @param vo 5 * @return 6 */ 7 @RequestMapping(value = "userAuth", method = RequestMethod.POST) 8 public InvokeResult userAuth(MobileAuthReqVo vo) { 9 InvokeResult invokeResult = null; 10 if (null == vo || CommonUtils.isEmpty(vo.getLoginname(), vo.getPassword())) { 11 invokeResult = InvokeResult.failure("请填写手机号和验证码!"); 12 } else if (!CommonUtils.isChinaPhoneLegal(vo.getLoginname())) { 13 invokeResult = InvokeResult.failure("手机号格式有误!"); 14 } else { 15 //用户登陆IP 16 String loginIp = vo.getUserpriip(); 17 int serialNo = (int) (65535 * Math.random()); 18 PortalV1PapMsgSender sender = new PortalV1PapMsgSender(); 19 sender.setTimeOut(60000); 20 try { 21 PortalV1Msg reciveMsg = sender.sendAndParseReqAuth(serialNo, loginIp, vo.getLoginname(), vo.getPassword(), acIp, acPort); 22 sender.sendAffAckAuth(serialNo, loginIp, acIp, acPort); 23 //重置密码,防止密码可以多次使用 24 Radcheck radcheck = new Radcheck() ; 25 radcheck.setUsername(vo.getLoginname()); 26 radcheck.setLoginIp(loginIp); 27 radcheck.setDeviceMac(vo.getDeviceMac()); 28 radcheck.updateIpAndMac(); 29 invokeResult = InvokeResult.ok(); 30 } catch (BizException e) { 31 e.printStackTrace(); 32 invokeResult = InvokeResult.failure(e.getMessage()); 33 } catch (Exception e) { 34 e.printStackTrace(); 35 invokeResult = InvokeResult.error(); 36 } 37 38 } 39 return invokeResult; 40 }
原文地址:https://www.cnblogs.com/FlyingPuPu/p/8503603.html
时间: 2024-11-14 12:05:09