一、报文封装类
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 }
View Code
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 }
View Code
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 }
View Code
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 }
View Code
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 }
View Code
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 }
View Code
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 }
View Code
二、工具类
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 }
View Code
三、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 }
View Code
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 }
View Code
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 }
View Code
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 }
View Code
四、使用示例
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 }
View Code