分析解读一次TinyRadius运行流程 入门:步骤分明,简洁明了
https://github.com/ctran/TinyRadius
radius资源网
http://tinyradius.sourceforge.net/
你必须要知道的
Radius客户端想要连接到服务端至少需要什么条件?
四个条件:
例如 localhost,
密钥:
例如 testing123
用户名:
例如 mw
密码:
例如 test
RadiusServer server = new RadiusServer(); server.start(true,true);
server.start()方法传入的参数是什么意思?
是否让服务端开启对认证端口 1812 ,记账端口1813的监听。
我们肯定是要开启的,所以传入true;
分别是
getSharedSecre 获取客户端密钥
getUserPassword 获取客户端密码
accessRequestReceived 获取客户端传来的报文
如下:
RadiusServer server = new RadiusServer() { (1): public String getSharedSecret(InetSocketAddress client) { return null; } (2): public String getUserPassword(String userName) { } (3): public RadiusPacket accessRequestReceived(AccessRequest accessRequest, InetSocketAddress client) throws RadiusException { } } server.start(true, true);
server.start()方法做了一件什么事?
截取该方法部分代码,清晰明了,如下:
是true启动一个线程
线程只做了一件事:调用listenAuth()方法
public void start(boolean listenAuth, boolean listenAcct) { if (listenAuth) { new Thread() { public void run() { setName("Radius Auth Listener"); try { log.info("启动 AuthListener 端口:{},调用listenAuth() " ,getAuthPort()); listenAuth(); //调用 listenAuth() logger.info("RadiusAuthListener is being terminated"); } catch (Exception e) { e.printStackTrace(); logger.fatal("auth thread stopped by exception", e); } finally { authSocket.close(); logger.debug("auth socket closed"); } } }.start(); } //.......... }
get到authsocket;
调用listen()方法;
protected void listenAuth() throws SocketException { listen(getAuthSocket()); //拿到socket 传给listen() }
-
它帮我们创建了一个阻塞式socket;
-
并且给socket绑定端口,1812或者1813.
protected DatagramSocket getAuthSocket() throws SocketException { if (authSocket == null) { if (getListenAddress() == null) authSocket = new DatagramSocket(getAuthPort()); else authSocket = new DatagramSocket(getAuthPort(), getListenAddress()); authSocket.setSoTimeout(getSocketTimeout()); } return authSocket; }
接收socket消息。
protected void listen(final DatagramSocket s) { while (true) { s.receive(packetIn); //..... } }
接收完消息它会对消息进行一系列的check,这是listen 下半部分的关键性代码。
if (executor == null) { log.info("报文接收线程为null,直接调用processRequest(s, packetIn);"); log.info("调用processRequest方法"); processRequest(s, packetIn); } else { log.info("报文接收线程存在,submit Runnable(run(processRequest(s, packetIn)))"); executor.submit(new Runnable() { @Override public void run() { processRequest(s, packetIn); } }); }
它做了以下操作
-
判断密钥
-
对报文进行解码处理
-
对请求报文copy,随后将响应报文添加其上
-
send(packet) 发送报文
截取部分代码如下:
//一系列check 首先检测密钥
if (secret == null) { log.info("processRequest():secret不存在!"); if (logger.isInfoEnabled()) logger.info("ignoring packet from unknown client " + remoteAddress + " received on local address " + localAddress); return; } log.info("makeRadiusPacket(),处理报文(解码处理等)."); // parse packet final RadiusPacket request = makeRadiusPacket(packetIn, secret, RadiusPacket.UNDEFINED); if (logger.isInfoEnabled()) logger.info("received packet from " + remoteAddress + " on local address " + localAddress + ": " + request); // handle packet logger.trace("about to call RadiusServer.handlePacket()"); log.info("handlePacket(),构建radius响应报文(中间会将请求报文copy并且拼接返回报文)"); final RadiusPacket response = handlePacket(localAddress, remoteAddress, request, secret); // send response if (response != null) { log.info("radius报文转化为socket--》》send()"); if (logger.isInfoEnabled()) logger.info("send response: " + response); final DatagramPacket packetOut = makeDatagramPacket(response, secret, remoteAddress.getAddress(), packetIn.getPort(), request); s.send(packetOut); }
client端开始
客户端做的事情很少
-
new client
-
传入4个关键参数
-
建立报文
-
调用认证与记账方法。
参数:localhost testing123 mw test
关键点:每个客户端发送报文后,就要阻塞住等待客户端的响应。
socket.send(packetOut);
socket.receive(packetIn);
初始化代码如下:
RadiusClient rc = new RadiusClient(host, shared); //创建报文 AccessRequest ar = new AccessRequest(user, pass); ar.setAuthProtocol(AccessRequest.AUTH_PAP); // or AUTH_CHAP ar.addAttribute("NAS-Identifier", "this.is.my.nas-identifier.de"); ar.addAttribute("NAS-IP-Address", "192.168.0.100"); ar.addAttribute("Service-Type", "Login-User"); ar.addAttribute("WISPr-Redirection-URL", "http://www.sourceforge.net/"); ar.addAttribute("WISPr-Location-ID", "net.sourceforge.ap1"); //调用认证方法 RadiusPacket response = rc.authenticate(ar); rc.close();
本文来自博客园,作者:无上仰无,转载请注明原文链接:https://www.cnblogs.com/sharey/articles/14986494.html

浙公网安备 33010602011771号