zoukankan      html  css  js  c++  java
  • 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
    
    
    















  • 相关阅读:
    ubuntu下无法在目录下创建文件夹,权限不足解决办法
    mongo中的模糊查询
    mysql中的模糊查询
    mysql安装与配置详情
    Django model中的class Meta详解
    kafka集群搭建
    myeclipse/eclipse添加Spket插件实现ExtJs4.2/ExtJs3智能提示
    博客园自定义标题、阅读目录、导航栏、活动的推荐&反对按钮
    IntelliJ IDEA 14 创建maven项目二
    EXT4.2--Ext Designer 使用
  • 原文地址:https://www.cnblogs.com/FlyingPuPu/p/8503603.html
Copyright © 2011-2022 走看看