本篇内容主要讲解“怎么用Java实现Radius客户端功能”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么用Java实现Radius客户端功能”吧!
使用Java实现Radius客户端,和服务端进行交互。(当前只实现了PAP模式)
主要代码如下: RadiusClient.java
package radius;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* 0 1 2 3
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Code | Identifier | Length |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | |
* | Authenticator |
* | |
* | |
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
* | Attributes ...
* +-+-+-+-+-+-+-+-+-+-+-+-+-
*/
public class RadiusClient {
private String secret;
private String ip;
private int port;
public RadiusClient(String secret, String ip, int port) {
this.secret = secret;
this.ip = ip;
this.port = port;
}
public byte[] generateAuthRequest(PacketType packetType, String username, char[] password)
throws IOException, NoSuchAlgorithmException {
return getSendBytes(packetType.code, username, password);
}
private void receive(DatagramSocket ds) throws IOException {
byte[] bs = new byte[4096];
DatagramPacket packet = new DatagramPacket(bs, bs.length);
ds.receive(packet);
System.out.println("receive success.");
int recvType = bs[0];
if (recvType == PacketType.ACCESS_ACCEPT.code) {
System.out.println(PacketType.ACCESS_ACCEPT.name());
parseResponse(bs);
} else if (recvType == PacketType.ACCESS_REJECT.code) {
System.out.println(PacketType.ACCESS_REJECT.name());
parseResponse(bs);
} else {
System.err.println("invalid response packet type: " + recvType);
}
}
private void parseResponse(byte[] bs) {
int identifier = bs[1];
int len = bs[2];
len = len << 8;
len = len | bs[3];
System.out.println("response length: " + len);
resolveAttr(bs, len);
}
private void resolveAttr(byte[] bs, int totalLen) {
int index = 20;
while (index < totalLen) {
int type = bs[index++];
int len = bs[index++];
byte[] attrValue = new byte[len - 2];
System.arraycopy(bs, index, attrValue, 0, attrValue.length);
index += attrValue.length;
System.out.println(String.format("attr type: %s, value: %s", type, new String(attrValue)));
}
}
public void send(byte[] data) {
DatagramSocket ds = null;
try {
ds = new DatagramSocket();
DatagramPacket packet = new DatagramPacket(data, data.length, InetAddress.getByName(ip), port);
ds.send(packet);
System.out.println("sent success.");
receive(ds);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ds != null) {
ds.close();
}
}
}
private byte[] getSendBytes(int accessType, String username, char[] password)
throws NoSuchAlgorithmException, IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bos.write(accessType); // Code
Random ran = new Random();
bos.write(ran.nextInt(255)); // Identifier
// Authenticator
byte[] authenticator = randomBytes(16);
List<RadiusAttr> attrs = new ArrayList<>();
attrs.add(new RadiusAttr(1, username.getBytes()));
// password
byte[] cipherPwd = encryptPassword(password, authenticator);
attrs.add(new RadiusAttr(2, cipherPwd));
int length = calculateTotalLength(attrs); // Length
System.out.println("request length: " + length);
int highLen = length >> 8;
bos.write(highLen);
bos.write(length);
bos.write(authenticator); // Authenticator
for (RadiusAttr attr : attrs) {
bos.write(attr.getType());
bos.write(attr.length());
bos.write(attr.getValue());
}
return bos.toByteArray();
}
private byte[] encryptPassword(char[] pwd, byte[] authenticator) throws NoSuchAlgorithmException {
if (pwd.length > 128) {
throw new IllegalArgumentException("password length is too long: " + pwd.length);
}
byte[] pwdBytes = new String(pwd).getBytes();
List<byte[]> cipherBlocks = new ArrayList<>();
for (int i = 0; i < pwdBytes.length; i += 16) {
byte[] pwdI = new byte[16];
int tmpLen = 16;
if (i + 16 >= pwdBytes.length) {
tmpLen = pwdBytes.length - i;
}
System.arraycopy(pwdBytes, i, pwdI, 0, tmpLen);
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(secret.getBytes());
if (cipherBlocks.isEmpty()) {
md.update(authenticator);
} else {
md.update(cipherBlocks.get(cipherBlocks.size() - 1));
}
byte[] md5 = md.digest();
byte[] result = new byte[16];
for (int j = 0; j < result.length; j++) {
result[j] = (byte) (pwdI[j] ^ md5[j]);
}
cipherBlocks.add(result);
}
List<Byte> list = new ArrayList<>();
for (byte[] bs : cipherBlocks) {
for (byte b : bs) {
list.add(b);
}
}
byte[] result = new byte[list.size()];
for (int i = 0; i < result.length; i++) {
result[i] = list.get(i);
}
return result;
}
private static int calculateTotalLength(List<RadiusAttr> attrs) {
int len = 20; // code + identifier + length + authenticator
for (RadiusAttr attr : attrs) {
len += attr.length();
}
return len;
}
private static byte[] randomBytes(int length) {
byte[] bs = new byte[length];
Random ran = new Random();
for (int i = 0; i < length; i++) {
bs[i] = (byte) ran.nextInt(255);
}
return bs;
}
}
调用方法:
package radius;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
public class ClientTest {
public static void main(String[] args) throws IOException, NoSuchAlgorithmException {
String secret = "secret";
String ip = "192.168.1.1";
int port = 1812;
RadiusClient radiusClient = new RadiusClient(secret, ip, port);
byte[] bs = radiusClient.generateAuthRequest(PacketType.ACCESS_REQUEST,
"username", "password".toCharArray());
radiusClient.send(bs);
}
}
到此,相信大家对“怎么用Java实现Radius客户端功能”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。
原文链接:https://my.oschina.net/u/2250875/blog/5050488