wifi认证Portal开发系列(四):portal协议的java封装

 一、报文封装类

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

 
















posted @ 2018-03-04 00:36  睡猪遇上狼  阅读(2617)  评论(3编辑  收藏  举报