一、报文封装类

AbstractPortalMsg.java
Portal协议数据报文封装类
 package org.yoki.edu.common.protocol.portal.msg;

 import lombok.Data;
import lombok.ToString;
import org.yoki.edu.common.protocol.portal.msg.attr.MsgAttr; import java.util.ArrayList;
import java.util.List; /**
* Portal协议数据报文封装类
*
* @author Sky$
* @Description: TODO
* @date 2017/10/24$ 19:16$
*/
@Data
@ToString
public abstract class AbstractPortalMsg { protected int ver;
protected int type;
protected int papChap = 1;
protected int rsvd = 0;
protected int serialNo;
protected int reqId;
protected String userIp;
protected int userPort = 0;
protected int errCode;
protected int attrNum;
/**
* 属性列表
*/
protected List<MsgAttr> attrList = new ArrayList<>(); /**
* 添加属性的方法
*
* @param attr
* @return
*/
public List<MsgAttr> addMsgAttr(MsgAttr attr) {
if (null == attrList) {
attrList = new ArrayList<>();
}
attrList.add(attr);
return attrList;
} /**
* 将hander部分的字段转化为16个字节
*
* @return
*/
protected byte[] getHander16Bytes() {
byte[] b = new byte[16];
b[0] = (byte) (ver & 0xff);
b[1] = (byte) (type & 0xff);
b[2] = (byte) (papChap & 0xff);
b[3] = (byte) (rsvd & 0xff);
b[4] = (byte) (serialNo >> 8 & 0xff);
b[5] = (byte) (serialNo & 0xff);
b[6] = (byte) (reqId >> 8 & 0xff);
b[7] = (byte) (reqId & 0xff);
byte[] ip = ipv4Address2BinaryArray(userIp);
System.arraycopy(ip, 0, b, 8, 4);
b[12] = (byte) (userPort >> 8 & 0xff);
b[13] = (byte) (userPort & 0xff);
b[14] = (byte) (errCode & 0xff);
b[15] = (byte) (attrNum & 0xff);
return b;
} /**
* 将属性列表转化为字节数组
*
* @return
*/
protected byte[] getAttrBytes() {
int attrByteNum = 0;
if (attrList != null && !attrList.isEmpty()) {
for (MsgAttr a : attrList) {
attrByteNum += a.getAttrLen();
}
}
byte[] b = new byte[attrByteNum];
int index = 0;
if (attrList != null && !attrList.isEmpty()) {
for (MsgAttr a : attrList) {
System.arraycopy(a.getByteValues(), 0, b, index, a.getByteValues().length);
index += a.getByteValues().length;
}
}
return b;
} /**
* 抽象方法:获取该报文类的字节数组<br>
* 抽象出该方法是因为移动Portal和华为Portal协议有些区别<br>
* 华为Portal有一个MD5加密字段
*
* @return
*/
public abstract byte[] toByteArray(); /**
* 抽象方法:通过报文字节数组,解析出各个字段值,并赋值<br>
* 抽象出该方法是因为移动Portal和华为Portal协议有些区别<br>
* 华为Portal有一个MD5加密字段
*
* @param input Portal协议报文字节数组
*/
public abstract void parse(byte[] input); /**
* 通过报文字节数组,解析出header部分的信息,并赋值
*
* @param input Portal协议报文字节数组
*/
protected void parseHeader(byte[] input) {
this.setVer(input[0]);
this.setType(input[1]);
this.setPapChap(input[2]);
this.setRsvd(input[3]); this.setSerialNo(((0xff & input[4]) << 8) | (0xff & input[5]));
this.setReqId(((0xff & input[6]) << 8) | (0xff & input[7])); this.setUserIp((input[8] & 0xff) + "." + (input[9] & 0xff) + "." + (input[10] & 0xff) + "." + (input[11] & 0xff));
this.setUserPort(((0xff & input[12]) << 8) | (0xff & input[13])); this.setErrCode(0xff & input[14]);
this.setAttrNum(0xff & input[15]);
} /**
* 通过报文字节数组,解析出attr部分的信息,并赋值
*
* @param attrBytes attr数组的字节数组
* @param attrNum attr的个数
*/
protected void parseAttr(byte[] attrBytes, int attrNum) {
List<MsgAttr> attrList = new ArrayList<MsgAttr>();
int count = attrNum;
if (count > 0) {
int t = 0;
for (int i = 0; i < count; i++) {
int attrType = attrBytes[t];
int attrLen = attrBytes[t + 1];
byte[] d = new byte[attrLen - 2];
System.arraycopy(attrBytes, t + 2, d, 0, attrLen - 2);
MsgAttr c = new MsgAttr(attrType, new String(d));
attrList.add(c);
t += c.getAttrLen();
}
}
this.setAttrList(attrList);
} /**
* IP地址转换工具方法,将IP字符串转换为字节数组
*
* @param ipAdd
* @return
*/
protected byte[] ipv4Address2BinaryArray(String ipAdd) {
byte[] binIP = new byte[4];
String[] strs = ipAdd.split("\\.");
for (int i = 0; i < strs.length; i++) {
binIP[i] = (byte) Integer.parseInt(strs[i]);
}
return binIP;
} }

PortalV1Msg.java
移动Portal协议数据报文封装类
 package org.yoki.edu.common.protocol.portal.msg;

 import lombok.NoArgsConstructor;
import org.yoki.edu.common.protocol.portal.msg.attr.MsgAttr; import java.util.List; /**
* 移动Portal协议数据报文封装类
*
* @author Sky$
* @Description: TODO
* @date 2017/10/25$ 14:52$
*/
@NoArgsConstructor
public class PortalV1Msg extends AbstractPortalMsg { public PortalV1Msg(int ver, int type, int serialNo, int reqId, String userIp, int errCode, int attrNum, List<MsgAttr> attr) {
super();
this.ver = ver;
this.type = type;
this.serialNo = serialNo;
this.reqId = reqId;
this.userIp = userIp;
this.errCode = errCode;
this.attrNum = attrNum;
this.attrList = attr;
} public PortalV1Msg(int ver, int type, int papChap, int rsvd, int serialNo, int reqId, String userIp, int userPort,
int errCode, int attrNum, List<MsgAttr> attr) {
super();
this.ver = ver;
this.type = type;
this.papChap = papChap;
this.rsvd = rsvd;
this.serialNo = serialNo;
this.reqId = reqId;
this.userIp = userIp;
this.userPort = userPort;
this.errCode = errCode;
this.attrNum = attrNum;
this.attrList = attr;
} @Override
public byte[] toByteArray() {
byte[] headerBytes = getHander16Bytes();
byte[] attrBytes = getAttrBytes();
byte[] b = new byte[headerBytes.length + attrBytes.length];
if (null != headerBytes && headerBytes.length > 0) {
System.arraycopy(headerBytes, 0, b, 0, headerBytes.length);
}
b[15] = (byte) this.attrList.size();
if (null != attrBytes && attrBytes.length > 0) {
System.arraycopy(attrBytes, 0, b, 16, attrBytes.length);
}
return b;
} @Override
public void parse(byte[] input) { if (null != input && input.length >= 16) {
byte[] headerBytes = new byte[16];
System.arraycopy(input, 0, headerBytes, 0, headerBytes.length);
this.parseHeader(headerBytes); int attrNum = input[15];
byte[] attrBytes = new byte[input.length - 16];
System.arraycopy(input, 16, attrBytes, 0, attrBytes.length);
parseAttr(attrBytes, attrNum);
} } }
MsgAttr.java
Portal数据报文Attr字段封装父类
 package org.yoki.edu.common.protocol.portal.msg.attr;

 import lombok.Data;
import lombok.Getter;
import lombok.NoArgsConstructor; import java.util.Arrays; /**
* Portal数据报文Attr字段封装父类
*
* @author Sky$
* @Description: TODO
* @date 2017/10/24$ 20:44$
*/
@Data
public class MsgAttr { private int attrType;
private int attrLen;
private String attrValue;
private byte[] byteValues; protected MsgAttr() { } public MsgAttr(int attrType, String attrValue) {
this.attrType = attrType;
this.attrLen = 2 + attrValue.getBytes().length;
this.attrValue = attrValue; byteValues = new byte[attrLen];
byteValues[0] = (byte) attrType;
byteValues[1] = (byte) attrLen;
System.arraycopy(attrValue.getBytes(), 0, byteValues, 2, attrValue.getBytes().length);
} }

UserNameMsgAttr.java
 package org.yoki.edu.common.protocol.portal.msg.attr;

 /**
* @author Sky$
* @Description: TODO
* @date 2017/10/29$ 15:05$
*/
public class UserNameMsgAttr extends MsgAttr { public UserNameMsgAttr(String userName){
super(0x01 , userName) ;
} }
PasswordMsgAttr.java
 package org.yoki.edu.common.protocol.portal.msg.attr;

 /**
* @author Sky$
* @Description: TODO
* @date 2017/10/29$ 15:08$
*/
public class PasswordMsgAttr extends MsgAttr { public PasswordMsgAttr(String password){
super(0x02 , password) ;
} }

ChallengeMsgAttr.java
 package org.yoki.edu.common.protocol.portal.msg.attr;

 /**
* @author Sky$
* @Description: TODO
* @date 2017/10/29$ 15:09$
*/
public class ChallengeMsgAttr extends MsgAttr { public ChallengeMsgAttr(String challenge){
super(0x03 , challenge) ;
} }
ChapPasswordMsgAttr.java
 package org.yoki.edu.common.protocol.portal.msg.attr;

 /**
* @author Sky$
* @Description: TODO
* @date 2017/10/29$ 15:09$
*/
public class ChapPasswordMsgAttr extends MsgAttr { public ChapPasswordMsgAttr(String chapPassword){
super(0x04 , chapPassword) ;
} }

二、工具类
ChapEncryptUtils.java
Chap加密工具类
 package org.yoki.edu.common.protocol.portal.utils;

 import org.yoki.edu.common.utils.encrypt.EncryptUtils;

 /**
* Chap加密
*
* @author Sky$
* @Description: TODO
* @date 2017/10/27$ 17:20$
*/
public class ChapEncryptUtils { public static byte[] encryptChap(int reqId, String challenge, String pwd) {
byte[] chapPwd = encryptChap(reqId, challenge.getBytes(), pwd.getBytes());
return chapPwd;
} public static byte[] encryptChap(int reqId, byte[] challenge, byte[] pwd) {
/**
* Chap_Password(Chap密码)的生成:
* Chap_Password的生成遵循标准的Radious协议中的Chap_Password 生成方法(参见RFC2865)。
* 密码加密使用MD5算法,MD5函数的输入为ChapID + Password +Challenge (reqId有AC生成, ChapID是ReqID的低8位)
* 其中,ChapID取reqId的低 8 位,Password的长度不够协议规定的最大长度,其后不需要补零。
* Chap_Password = MD5 (ChapID+ Password + Challenge )
*/
byte[] buf = new byte[1 + pwd.length + challenge.length];
buf[0] = (byte) (reqId & 0xff);
System.arraycopy(pwd, 0, buf, 1, pwd.length);
System.arraycopy(challenge, 0, buf, 1 + pwd.length, challenge.length);
byte[] chapPwd = EncryptUtils.encryptMD5Bytes(buf);
return chapPwd;
} }

三、Portal协议工具类
PortalV1ChapMsgBuilder.java
CHAP方式Portal报文生产工具类
 package org.yoki.edu.common.protocol.portal.v1.builder;

 import org.yoki.edu.common.protocol.portal.msg.attr.UserNameMsgAttr;
import org.yoki.edu.common.protocol.portal.utils.ChapEncryptUtils;
import org.yoki.edu.common.protocol.portal.msg.PortalV1Msg;
import org.yoki.edu.common.protocol.portal.msg.attr.ChapPasswordMsgAttr; /**
* CHAP方式Portal报文生产工具类
*
* @author Sky$
* @Description: TODO
* @date 2017/10/29$ 14:37$
*/
public class PortalV1ChapMsgBuilder { /**
* 生成Chanllenge请求报文
*
* @param serialNo
* @param userIp 用户IP
* @return
*/
public PortalV1Msg buildReqChallengeMsg(int serialNo, String userIp) {
PortalV1Msg msg = buildV1ChapMsg();
msg.setType(1);
msg.setReqId(0);
msg.setSerialNo(serialNo);
msg.setUserIp(userIp);
msg.setAttrNum(0);
return msg;
} /**
* 生成认证请求报文
*
* @param reqId
* @param serialNo
* @param userIp
* @param userName
* @param password
* @param challenge
* @return
*/
public PortalV1Msg buildReqAuthMsg(int reqId, int serialNo, String userIp, String userName, String password, String challenge) {
PortalV1Msg msg = buildV1ChapMsg();
msg.setType(3);
msg.setSerialNo(serialNo);
msg.setReqId(reqId);
msg.setUserIp(userIp);
msg.setAttrNum(2);
UserNameMsgAttr userNameMsgAttr = new UserNameMsgAttr(userName);
byte[] chapPassworldBytes = ChapEncryptUtils.encryptChap(reqId, challenge, password);
ChapPasswordMsgAttr chapPasswordMsgAttr = new ChapPasswordMsgAttr(new String(chapPassworldBytes));
msg.addMsgAttr(userNameMsgAttr).add(chapPasswordMsgAttr);
return msg;
} /**
* 生成下线请求报文
*
* @param reqId
* @param serialNo
* @param userIp
* @return
*/
public PortalV1Msg buildReqLogoutMsg(int reqId, int serialNo, String userIp) {
PortalV1Msg msg = buildV1ChapMsg();
msg.setType(5);
msg.setSerialNo(serialNo);
msg.setReqId(reqId);
msg.setUserIp(userIp);
msg.setAttrNum(0);
return msg;
} /**
* 生成认证接收响应报文
*
* @param reqId
* @param serialNo
* @param userIp
* @return
*/
public PortalV1Msg buildAffAckAuthMsg(int reqId, int serialNo, String userIp) {
PortalV1Msg msg = buildV1ChapMsg();
msg.setType(7);
msg.setSerialNo(serialNo);
msg.setReqId(reqId);
msg.setUserIp(userIp);
msg.setAttrNum(0);
return msg;
} private PortalV1Msg buildV1ChapMsg() {
PortalV1Msg msg = new PortalV1Msg();
msg.setVer(1); msg.setPapChap(0);
msg.setRsvd(0); msg.setUserPort(0);
msg.setErrCode(0);
return msg;
} }


PortalV1PapMsgBuilder.java
PAP方式Portal报文生产工具类
 package org.yoki.edu.common.protocol.portal.v1.builder;

 import org.yoki.edu.common.protocol.portal.msg.PortalV1Msg;
import org.yoki.edu.common.protocol.portal.msg.attr.PasswordMsgAttr;
import org.yoki.edu.common.protocol.portal.msg.attr.UserNameMsgAttr; /**
* PAP方式Portal报文生产工具类
*
* @author Sky$
* @Description: TODO
* @date 2017/10/29$ 14:37$
*/
public class PortalV1PapMsgBuilder { /**
* 生成认证请求报文
*
* @param serialNo
* @param userIp
* @param userName
* @param password
* @return
*/
public PortalV1Msg buildReqAuthMsg(int serialNo, String userIp, String userName, String password) {
PortalV1Msg msg = buildV1PapMsg();
msg.setType(3);
msg.setSerialNo(serialNo); msg.setUserIp(userIp);
msg.setAttrNum(2);
UserNameMsgAttr userNameMsgAttr = new UserNameMsgAttr(userName);
PasswordMsgAttr passwordMsgAttr = new PasswordMsgAttr(password);
msg.addMsgAttr(userNameMsgAttr).add(passwordMsgAttr);
return msg;
} /**
* 生成下线请求报文
*
* @param serialNo
* @param userIp
* @return
*/
public PortalV1Msg buildReqLogoutMsg(int serialNo, String userIp) {
PortalV1Msg msg = buildV1PapMsg();
msg.setType(5);
msg.setSerialNo(serialNo);
msg.setUserIp(userIp);
msg.setAttrNum(0);
return msg;
} /**
* 生成认证接收响应报文
*
* @param serialNo
* @param userIp
* @return
*/
public PortalV1Msg buildAffAckAuthMsg(int serialNo, String userIp) {
PortalV1Msg msg = buildV1PapMsg();
msg.setType(7);
msg.setSerialNo(serialNo);
msg.setUserIp(userIp);
msg.setAttrNum(0);
return msg;
} private PortalV1Msg buildV1PapMsg() {
PortalV1Msg msg = new PortalV1Msg();
msg.setVer(1); msg.setPapChap(1);
msg.setRsvd(0); msg.setReqId(0); msg.setUserPort(0);
msg.setErrCode(0);
return msg;
} }

PortalV1MsgParser.java
报文解析工具类
 package org.yoki.edu.common.protocol.portal.v1.parser;

 import org.yoki.edu.common.protocol.portal.exception.PortalException;
import org.yoki.edu.common.protocol.portal.exception.enums.PortalErrorStatusEnum;
import org.yoki.edu.common.protocol.portal.msg.PortalV1Msg; /**
* 报文解析工具类
*
* @author Sky$
* @Description: TODO
* @date 2017/10/29$ 15:59$
*/
public class PortalV1MsgParser { private final int ACK_CHALLENGE = 0X02;
private final int ACK_AUTH = 0X04;
private final int ACK_LOGOUT = 0X06; private final int ERROR_CODE_1 = 1;
private final int ERROR_CODE_2 = 2;
private final int ERROR_CODE_3 = 3;
private final int ERROR_CODE_4 = 4; public PortalV1Msg parse(byte[] input) throws PortalException {
PortalV1Msg msg = new PortalV1Msg();
msg.parse(input);
parse(msg);
return msg;
} public void parse(PortalV1Msg msg) throws PortalException {
Integer type = msg.getType();
Integer errorCode = msg.getErrCode();
PortalErrorStatusEnum[] enums = PortalErrorStatusEnum.values();
for (PortalErrorStatusEnum e : enums) {
if (e.getErrCode() == errorCode && e.getType() == type) {
throw new PortalException(e);
}
}
} }
PortalV1PapMsgSender.java
Portal报文发送工具类
内部调用DatagramSocket进行UDP报文发送
 package org.yoki.edu.common.protocol.portal.v1.sender;

 import lombok.Getter;
import lombok.Setter;
import org.yoki.edu.common.protocol.portal.v1.builder.PortalV1PapMsgBuilder;
import org.yoki.edu.common.protocol.portal.exception.PortalException;
import org.yoki.edu.common.protocol.portal.msg.PortalV1Msg;
import org.yoki.edu.common.protocol.portal.v1.parser.PortalV1MsgParser; import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress; /**
* Portal报文发送工具类<br>
* 内部调用DatagramSocket进行UDP报文发送
*
* @author Sky$
* @Description: TODO
* @date 2017/10/31$ 17:57$
*/
public class PortalV1PapMsgSender { @Setter
@Getter
private int timeOut = 5000; @Setter
@Getter
private Integer receiverPort = null; /**
* REQ_AUTH 0x03 Client----->Server AbstractPortalMsg Server向AC设备发送的请求认证报文
*
* @param serialNo
* @param loginIp
* @param loginName
* @param password
* @param acIp
* @param acPort
* @return
* @throws Exception
*/
public byte[] sendReqAuth(int serialNo, String loginIp, String loginName, String password, String acIp, int acPort) throws IOException {
DatagramSocket dataSocket = null;
byte[] ackData = new byte[0];
dataSocket = null;
DatagramPacket requestPacket = null;
PortalV1PapMsgBuilder builder = new PortalV1PapMsgBuilder();
PortalV1Msg msg = builder.buildReqAuthMsg(serialNo, loginIp, loginName, password);
byte[] msgBytes = msg.toByteArray();
// 创建连接
if (null != receiverPort) {
dataSocket = new DatagramSocket(receiverPort);
} else {
dataSocket = new DatagramSocket();
}
// 创建发送数据包并发送给服务器
requestPacket = new DatagramPacket(msgBytes, msgBytes.length, InetAddress.getByName(acIp), acPort);
ackData = new byte[1024];
// 接收服务器的数据包
DatagramPacket receivePacket = new DatagramPacket(ackData, 32);
// 设置请求超时3秒
dataSocket.setSoTimeout(timeOut);
dataSocket.send(requestPacket);
dataSocket.receive(receivePacket); if (null != dataSocket) {
dataSocket.disconnect();
dataSocket.close();
}
return ackData; } /**
* REQ_AUTH 0x03 Client----->Server AbstractPortalMsg Server向AC设备发送的请求认证报文
*
* @param serialNo
* @param loginIp
* @param loginName
* @param password
* @param acIp
* @param acPort
* @return
* @throws Exception
*/
public PortalV1Msg sendAndParseReqAuth(int serialNo, String loginIp, String loginName, String password, String acIp, int acPort) throws PortalException, IOException {
byte[] ackData = sendReqAuth(serialNo, loginIp, loginName, password, acIp, acPort);
PortalV1MsgParser msgParser = new PortalV1MsgParser();
PortalV1Msg reciveMsg = msgParser.parse(ackData);
reciveMsg.parse(ackData);
return reciveMsg; } /**
* AbstractPortalMsg Server对收到的认证成功响应报文的确认报文;
*
* @param serialNo
* @param loginIp
* @param acIp
* @param acPort
* @throws Exception
*/
public void sendAffAckAuth(int serialNo, String loginIp, String acIp, int acPort) throws IOException {
DatagramSocket dataSocket = null;
PortalV1PapMsgBuilder builder = new PortalV1PapMsgBuilder();
PortalV1Msg msg = builder.buildAffAckAuthMsg(serialNo, loginIp);
byte[] msgBytes = msg.toByteArray();
// 创建连接
if (null != receiverPort) {
dataSocket = new DatagramSocket(receiverPort);
} else {
dataSocket = new DatagramSocket();
}
// 创建发送数据包并发送给服务器
DatagramPacket requestPacket = new DatagramPacket(msgBytes, msgBytes.length, InetAddress.getByName(acIp), acPort);
// 接收服务器的数据包
dataSocket.send(requestPacket);
if (null != dataSocket) {
dataSocket.disconnect();
dataSocket.close();
}
} /**
* AbstractPortalMsg Server向AC设备发送的请求用户下线报文
*
* @param serialNo
* @param loginIp
* @param acIp
* @param acPort
* @return
* @throws Exception
*/
public byte[] sendReqLogout(int serialNo, String loginIp, String acIp, int acPort) throws IOException {
DatagramSocket dataSocket = null;
byte[] ackData = new byte[0];
PortalV1PapMsgBuilder builder = new PortalV1PapMsgBuilder();
PortalV1Msg msg = builder.buildReqLogoutMsg(serialNo, loginIp);
byte[] msgBytes = msg.toByteArray();
// 创建连接
if (null != receiverPort) {
dataSocket = new DatagramSocket(receiverPort);
} else {
dataSocket = new DatagramSocket();
}
// 创建发送数据包并发送给服务器
DatagramPacket requestPacket = new DatagramPacket(msgBytes, msgBytes.length, InetAddress.getByName(acIp), acPort);
ackData = new byte[1024];
// 接收服务器的数据包
DatagramPacket receivePacket = new DatagramPacket(ackData, 32);
// 设置请求超时3秒
dataSocket.setSoTimeout(timeOut);
dataSocket.send(requestPacket);
dataSocket.receive(receivePacket);
if (null != dataSocket) {
dataSocket.disconnect();
dataSocket.close();
}
return ackData; } /**
* AbstractPortalMsg Server向AC设备发送的请求用户下线报文
*
* @param serialNo
* @param loginIp
* @param acIp
* @param acPort
* @return
* @throws Exception
*/
public PortalV1Msg sendAndParseReqLogout(int serialNo, String loginIp, String acIp, int acPort) throws IOException, PortalException {
byte[] ackData = sendReqLogout(serialNo, loginIp, acIp, acPort);
PortalV1MsgParser msgParser = new PortalV1MsgParser();
PortalV1Msg reciveMsg = msgParser.parse(ackData);
reciveMsg.parse(ackData);
return reciveMsg; } }

四、使用示例

 
 /**
* 用户短信认证
*
* @param vo
* @return
*/
@RequestMapping(value = "userAuth", method = RequestMethod.POST)
public InvokeResult userAuth(MobileAuthReqVo vo) {
InvokeResult invokeResult = null;
if (null == vo || CommonUtils.isEmpty(vo.getLoginname(), vo.getPassword())) {
invokeResult = InvokeResult.failure("请填写手机号和验证码!");
} else if (!CommonUtils.isChinaPhoneLegal(vo.getLoginname())) {
invokeResult = InvokeResult.failure("手机号格式有误!");
} else {
//用户登陆IP
String loginIp = vo.getUserpriip();
int serialNo = (int) (65535 * Math.random());
PortalV1PapMsgSender sender = new PortalV1PapMsgSender();
sender.setTimeOut(60000);
try {
PortalV1Msg reciveMsg = sender.sendAndParseReqAuth(serialNo, loginIp, vo.getLoginname(), vo.getPassword(), acIp, acPort);
sender.sendAffAckAuth(serialNo, loginIp, acIp, acPort);
//重置密码,防止密码可以多次使用
Radcheck radcheck = new Radcheck() ;
radcheck.setUsername(vo.getLoginname());
radcheck.setLoginIp(loginIp);
radcheck.setDeviceMac(vo.getDeviceMac());
radcheck.updateIpAndMac();
invokeResult = InvokeResult.ok();
} catch (BizException e) {
e.printStackTrace();
invokeResult = InvokeResult.failure(e.getMessage());
} catch (Exception e) {
e.printStackTrace();
invokeResult = InvokeResult.error();
} }
return invokeResult;
}


wifi认证Portal开发系列(四):portal协议的java封装的更多相关文章

  1. S5PV210开发系列四_uCGUI的移植

    S5PV210开发系列四 uCGUI的移植 象棋小子          1048272975 GUI(图形用户界面)极大地方便了非专业用户的使用,用户无需记忆大量的命令,取而代之的是能够通过窗体.菜单 ...

  2. 转:arcgis api for js入门开发系列四地图查询

    原文地址:arcgis api for js入门开发系列四地图查询 arcgis for js的地图查询方式,一般来说,总共有三种查询方式:FindTask.IdentifyTask.QueryTas ...

  3. wifi认证Portal开发系列(三):portal协议

    中国移动WLAN业务PORTAL协议规范介绍 一.用户上线认证流程 上线流程完成用户账号的认证,并把认证结果通知Portal Server,Portal server将会通知WLAN用户并且显示相应的 ...

  4. 【Qt编程】基于Qt的词典开发系列<四>--无边框窗口的缩放与拖动

    在现在,绝大多数软件都向着简洁,时尚发展.就拿有道的单词本和我做的单词本来说,绝大多数用户肯定喜欢我所做的单词本(就单单界面,关于颜色搭配和布局问题,大家就不要在意了). 有道的单词本: 我所做的单词 ...

  5. BizTalk 开发系列(四十一) BizTalk 2010 BAM 安装手记

    使用64位系统可以支持更大的内存,现在服务器基本上都使用64位系统.微软从Windows Server 2008 R2开始服务器版的操作系统也只支持64位了,不过对于像BizTalk这种“繁杂的东西” ...

  6. 微信小程序开发系列四:微信小程序之控制器的初始化逻辑

    微信小程序开发系列教程 微信小程序开发系列一:微信小程序的申请和开发环境的搭建 微信小程序开发系列二:微信小程序的视图设计 微信小程序开发系列三:微信小程序的调试方法 这个教程的前两篇文章,介绍了如何 ...

  7. leaflet-webpack 入门开发系列四图层控件样式优化篇(附源码下载)

    前言 leaflet-webpack 入门开发系列环境知识点了解: node 安装包下载webpack 打包管理工具需要依赖 node 环境,所以 node 安装包必须安装,上面链接是官网下载地址 w ...

  8. wifi认证Portal开发系列(二):FreeRadius的安装和测试、关联Mysql

    注:本次安装是基于FreeRadius 3版本进行安装配置的,在配置Mysql的过程中,与2版本有些不同.操作系统是CentOS 7 一.准备工作 工具的安装 #安装rz.sz命令用于文件上传 yum ...

  9. wifi认证Portal开发系列(一):Radius与FreeRadius简介

    RADIUS 维基百科上的介绍: Remote Authentication Dial-In User Service (RADIUS) is a networking protocol that p ...

随机推荐

  1. Java语法糖(一)

    概述 语法糖(Syntactic Sugar):主要作用是提高编码效率,减少编码出错的机会. 解语法糖发生在Java源码被编译成Class字节码的过程中,还原回简单的基础语法结构. 语法糖之一:泛型( ...

  2. Scrapy学习-24-集成elasticsearch

    elasticsearch简单集成到scrapy中 使用elasticsearch的python接口处理数据  https://github.com/elastic/elasticsearch-dsl ...

  3. ubuntu 12.04LTS下搭建Andriod开发环境记录

    今天在Ubuntu 12.04 LTS 下安装了android开发环境. 1, 安装JDK 先去 Oracle下载Linux下的JDK压缩包,我下载的是jdk-7u4-linux-i586.tar.g ...

  4. Python_代码练习_写一个判断是否为小数的函数

    这两天在学习函数,练习写一个判断是否为小数的函数,看起来蛮简单的,飞速写完很是得意,然后测了一下,发现差得好多呀,这个并不像想象那样简单,我得到的教训是,想要把一个需求哪怕再小的需求考虑周全,都不是件 ...

  5. C#使用DirectoryEntry类操作Windows帐户

    1.创建windows帐户 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 /// <summary> /// 创建Windows帐户 /// </summa ...

  6. C#Json转Xml格式数据的方法

    第一种方法 string Xml = "在这里写Json字符串"; XmlDictionaryReader reader = JsonReaderWriterFactory.Cre ...

  7. hdu 4985(模拟)

    Little Pony and Permutation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (J ...

  8. RadioGroup动态添加RadioButton,并且获得事件

    由于有许多的RadioButton是动态的,不是固定的一些,所以需要在代码中,动态的添加到RadioGroup中,下面是我的实现方法. 1.添加RadioButton到RadioGroup中 Radi ...

  9. ELK之filebeat替代logstash收集日志

    filebeat->redis->logstash->elasticsearch 官网下载地址:https://www.elastic.co/downloads/beats/file ...

  10. jeesite导入数据库错误:java.sql.SQLException: Incorrect string value: '\xE4\xB8\xAD\xE5\x9B\xBD' for column 'name' at row 1问题解决

    如果使用mvn antrun:run -Pinit-db进行数据库导入导致出现如下错误: 解决方法: 这个是由于新建数据库没有选择默认字符集导致的,只要选择utf-8即可.