网络对抗原理实验二



一,OpenLDAP 搭建 LDAP 服务器

用 OpenLDAP 搭建 LDAP 服务器,尝试对学生信息进行增删改查,信息包括但不限于学生 id 、密码、邮箱、手机号、部门等

1.1 ldap

$ sudo apt update
$ sudo apt install slapd ldap-utils    #安装配置软件
$ sudo dpkg-reconfigure slapd   #对slapd进行再配置
图片.png
图片.png

1.2安装phpldapadmin

sudo apt install phpldapadmin`

修改相应的配置文件/etc/phpldapadmin/config.php,做如下修改:


图片.png

防火墙放行Apache2:


图片.png

1.3测试登录

浏览器打开:http://127.0.0.1/phpldapadmin/index.php进入后登录

图片.png

登陆成功,利用phpldapadmin 的图形化界面,对学生数据增删改查后:


图片.png

1.4配置 Apache 服务器,配置 Basic 认证模块和需要认证的页面,使用用户名密码认证。

1.4.1搭建 Apache 服务

sudo apt-get install apache2

防火墙放行Apache2:

$ sudo ufw allow "Apache"
$ sudo ufw allow "Apache Full"
$ sudo ufw allow "Apache Secure"
$ sudo service apache2 restart    #重启Apache服务

新建一个验证页面

$ sudo mkdir /var/www/html/auth-basic
$ sudo vim /var/www/html/auth-basic/index.html
<html>
<body>
<div style="width: 100%; font-size: 40px; font-weight: bold; text-align: center;">
Basic Authentication is Successful.</br></br>
yewii yu</br>
2018.7.7
</div>
</body>
</html>

1.4.2待验证页面

浏览器访问 http://127.0.0.1/auth-basic/ 访问成功

图片.png

1.4.3配置一个本地目录的Basic基本认证

创建用户

$ sudo htpasswd -c /etc/apache2/.user richard     #第一次创建.user文件添加 -c 参数
New password: 
Re-type new password: 
Adding password for user richard

$ sudo cat /etc/apache2/.user     #查看密码文件
richard:$apr1$JUaFTlkk$T1BwFfn.kU9OaxvxdqUQD1

图片.png

修改本地Apache配置文件

$ sudo vim /etc/apache2/apache2.conf
# 找到这里
<Directory /var/www/>
    Options Indexes FollowSymLinks
    AllowOverride All
    Require all granted
</Directory>

图片.png

在授权目录下添创建.htaccess文件

$ sudo vim /var/www/html/auth-basic/.htaccess
AuthType Basic
AuthName "Basic Authentication"
AuthUserFile /etc/apache2/.user
Require valid-user
图片.png

重启 Apache

$ sudo service apache2 restart

1.4.4 测试认证

在浏览器访问 http://127.0.0.1/auth-basic/ 输入用户名密码登录即可正常访问

图片.png

图片.png

出错

Job for apache2.service failed because the control process exited with error code. See "systemctl status apache2.service" and "journalctl -xe" for details.`

2.配置 Apache 服务器,配置 LDAP 认证模块和需要认证的页面,使用 LDAP 存放的学生的用户名密码认证。

2.1 环境配置

安装ldap模块

$ a2enmod ldap authnz_ldap
Module ldap already enabled
Considering dependency ldap for authnz_ldap:
Module ldap already enabled
Module authnz_ldap already enabled

配置需要认证信息

$ sudo vim /etc/apache2/sites-available/auth-ldap.conf
#配置文件
<Directory "/var/www/html/auth-ldap">
    AuthName "LDAP Authentication"
    AuthType Basic
    AuthBasicProvider ldap
    AuthLDAPUrl "ldap://127.0.0.1/dc=example,dc=com"
    Require valid-user
</Directory>

创建配置页面

$ sudo mkdir /var/www/html/auth-ldap 
$ a2ensite auth-ldap
$ sudo vim /var/www/html/auth-ldap/index.html
<html>
<body>
<div style="width: 100%; font-size: 40px; font-weight: bold; text-align: center;">
Programming is Successfil.</br></br>
(|-_-|)</br></br>
yewii yu</br>
2018.7.18
</div>
</body>
</html>

重启Apache服务

$ sudo service apache2 restart
2.2 测试认证

浏览器访问:http://127.0.0.1/auth-ldap/

图片.png
图片.png

3.用 FreeRADIUS 搭建 Radius 服务器,尝试配置基于 Unix 账号的认证,并用 radtest 验证服务有效

3.1 安装 FreeRADIUS

$ sudo apt-get install freeradius

3.2 验证版本

图片.png

3.3 运行快速配置检查

$ sudo freeradius -CX
#结尾会回显
Configuration appears to be OK.
图片.png

3.4 查看配置文件

$ sudo vim /etc/freeradius/radiusd.conf

3.5 配置 Clients

sudo vim /etc/freeradius/clients.conf
# 这个是默认配置,如果在本地实验,无需改动
client localhost {
 ipaddr = 127.0.0.1
 secret = testing123
 }

3.6 添加用户

$ sudo vim /etc/freeradius/users
# 在配置文件中添加
richard  Cleartext-Password := "password"
         Reply-Message := "Hello,%{User-Name}"

3.7 重启 RADIUS

$ sudo service freeradius restart

3.8 测试认证

图片.png

3.9Start FreeRADIUS

图片.png

Radius 服务器配置完成!

4.配置 Apache 服务器,配置 Radius 认证模块和需要认证的页面,使用 Unix/Linux 本地用户名密码认证

4.1 环境配置

在 Apache2 上安装 Radius 身份验证所需的模块


图片.png

启动模块


图片.png

在Apache配置文件中添加认证
$ sudo vim /etc/apache2/apache2.conf
# 添加在配置文件 apache2.conf 中
AddRadiusAuth localhost:1812 testing123 5
AddRadiusCookieValid 60
# 下面这是模板
# AddRadiusAuth IP_OF_RADIUS_SERVER:PORT SECRET 5   
# AddRadiusCookieValid 60

创建配置页面

$ sudo mkdir /var/www/html/auth-radius
$ sudo vim /var/www/html/auth-radius/index.html
<html>
<body>
<div style="width: 100%; font-size: 40px; font-weight: bold; text-align: center;">
Radius Authentication is Successful.</br></br>
yewii yu</br>
(^_^)</br>
2018.7.18
</div>
</body>
</html>

在待验证⻚页面面添加 .htaccess 文文件

$ sudo vim /var/www/html/auth-radius/.htaccess
# 配置文件 .htaccess
AuthType Basic
AuthName "Radius Authentication"
AuthBasicAuthoritative Off
AuthBasicProvider radius
AuthRadiusAuthoritative on
AuthRadiusActive On
Require valid-user

重启 Apache 服务

$ sudo service apache2 restart
4.2 认证测试

浏览器访问:http://127.0.0.1/auth-radius/

图片.png

认证后:


图片.png

Radius 认证完成!

5.在 FreeRADIUS 中配置 ldap 认证模块,和 LDAP 服务器互通,利用 ldap 账号密码认证用户身份,并用radtest 测试通过。

5.1环境配置

安装 FreeRADIUS 和 OpenLDAP 模块

$ sudo apt install freeradius-ldap
ldap{
        server = "localhost"
        identity = "cn=admin,dc=example,dc=com"
        password = password
        basedn = "dc=example,dc=com"
        filter = "(uid=%{%{Stripped-User-Name}:-%{User-Name}})"
        ldap_connections_number = 5
        timeout = 4
        timelimit = 3
        net_timeout = 1
        dictionary_mapping = ${confdir}/ldap.attrmap
        edir_account_policy_check = no
        set_auth_type = yes
}
# 这些格式在配置文件中都有,只需修改对应的变量或删除对应参数前的#注释

配置以下参数以启动 ldap

$ sudo vim /etc/freeradius/sites-available/default
# 这里 . 是省略,只需删除对应 authorize 参数下 ldap 前的#注释即可
authorize {
.
.
ldap
.
.
}
$ sudo vim /etc/freeradius/sites-available/inner-tunnel
# 这里 . 是省略,只需删除对应 authorize 参数下 ldap 前的#注释即可
authorize {
.
.
ldap
.
.
}

5.2 通过 radtest 测试 LDAP 中的用户

以下是 LDAP 中以添加的用户


image.png

*这里 "cn=richard yan" 由于缩写实际 User Name=ryan

$ radtest ryan 123456 127.0.0.1 0 testing123
Sending Access-Request of id 190 to 127.0.0.1 port 1812
    User-Name = "yyu"
    User-Password = "1997424"
    NAS-IP-Address = 127.0.1.1
    NAS-Port = 0
    Message-Authenticator = 0x00000000000000000000000000000000
rad_recv: Access-Accept packet from host 127.0.0.1 port 1812, id=190, length=20

出现 Access-Accept 即证明用户可在 Radius 下登录认证。
LDAP用户认证完成!

6. 在之前 Apache 的 Radius 认证模块的配置下,不改变配置,切换到使用 LDAP 存放的学生用户名密码认证,体会这种配置和 3 的不同。

6.1 认证测试

浏览器访问 http://127.0.0.1/auth-radius/
这里使用的就是 LDAP 中存放的学生用户进行的认证:

image.png

登录后:


image.png

6.2 对比

LDAP提供目录服务,类似于企业、人员黄页的东西,用户和组织的信息都被存放在上面,查找起来十分快捷,也可以理解成一种特殊的数据库,而认证只是一方面,它的目标是按目录结点的方式来存取信息。
Radius是一种专门的认证协议,支持多样的认证方式。出了最常见的pap,chap等,还支持EAP(扩展认证协议),这是LDAP协议中没有的。
LDAP + Radius 有效的结合二者的特性,使认证更加系统化,方便目录管理而又兼顾了认证的安全性,可用于实现商业企业局域网统一认证系统。

图片.png

Radius 认证完成!

此时关闭 ModSecurity 模块

`Enabling _dnsCache()
Called buildOpeners
keepalive: added one connection, len(self._hostmap["127.0.0.1"]): 1
DNS response from DNS server for domain: 127.0.0.1
GET http://127.0.0.1/student/ returned HTTP code "403" - id: 1
[thread manager] Successfully added function to threadpool. Work queue size: 1
[thread manager] Successfully added function to threadpool. Work queue size: 2
[thread manager] Successfully added function to threadpool. Work queue size: 3
[thread manager] Successfully added function to threadpool. Work queue size: 4
[thread manager] Successfully added function to threadpool. Work queue size: 5
[thread manager] Successfully added function to threadpool. Work queue size: 6
[thread manager] Successfully added function to threadpool. Work queue size: 7
[thread manager] Successfully added function to threadpool. Work queue size: 8
[thread manager] Successfully added function to threadpool. Work queue size: 9
[thread manager] Successfully added function to threadpool. Work queue size: 10
[thread manager] Successfully added function to threadpool. Work queue size: 11
[thread manager] Successfully added function to threadpool. Work queue size: 12
[thread manager] Successfully added function to threadpool. Work queue size: 13
[thread manager] Successfully added function to threadpool. Work queue size: 14
keepalive: added one connection, len(self._hostmap["127.0.0.1"]): 2
Cached DNS response for domain: 127.0.0.1
keepalive: added one connection, len(self._hostmap["127.0.0.1"]): 3
Cached DNS response for domain: 127.0.0.1
keepalive: added one connection, len(self._hostmap["127.0.0.1"]): 4
Cached DNS response for domain: 127.0.0.1
keepalive: added one connection, len(self._hostmap["127.0.0.1"]): 5
Cached DNS response for domain: 127.0.0.1
GET http://127.0.0.1/student/ww1yYZl9.htm returned HTTP code "403" - id: 2
No grep for: "http://127.0.0.1/student/ww1yYZl9.htm", the plugin sent grep=False.
GET http://127.0.0.1/student/UBd6Bxxt.py returned HTTP code "403" - id: 3
No grep for: "http://127.0.0.1/student/UBd6Bxxt.py", the plugin sent grep=False.
GET http://127.0.0.1/student/boQkOdd9.asp returned HTTP code "403" - id: 6
GET http://127.0.0.1/student/Kq9Kl3OI.do returned HTTP code "403" - id: 5
No grep for: "http://127.0.0.1/student/Kq9Kl3OI.do", the plugin sent grep=False.
No grep for: "http://127.0.0.1/student/boQkOdd9.asp", the plugin sent grep=False.
GET http://127.0.0.1/student/5HE5HJbF.gif returned HTTP code "403" - id: 7
GET http://127.0.0.1/student/wkOiP2IM. returned HTTP code "403" - id: 4
No grep for: "http://127.0.0.1/student/wkOiP2IM.", the plugin sent grep=False.
No grep for: "http://127.0.0.1/student/5HE5HJbF.gif", the plugin sent grep=False.
GET http://127.0.0.1/student/y2mbi09u.htmls returned HTTP code "403" - id: 8
No grep for: "http://127.0.0.1/student/y2mbi09u.htmls", the plugin sent grep=False.
GET http://127.0.0.1/student/TGc5v5NN.rb returned HTTP code "403" - id: 9
No grep for: "http://127.0.0.1/student/TGc5v5NN.rb", the plugin sent grep=False.
GET http://127.0.0.1/student/EQp6IMrI.php returned HTTP code "403" - id: 10
No grep for: "http://127.0.0.1/student/EQp6IMrI.php", the plugin sent grep=False.
GET http://127.0.0.1/student/JDu6xd51.cgi returned HTTP code "403" - id: 11
No grep for: "http://127.0.0.1/student/JDu6xd51.cgi", the plugin sent grep=False.
GET http://127.0.0.1/student/xbnERvIu.jsp returned HTTP code "403" - id: 12
No grep for: "http://127.0.0.1/student/xbnERvIu.jsp", the plugin sent grep=False.
GET http://127.0.0.1/student/8mlVHdU5.aspx returned HTTP code "403" - id: 13
No grep for: "http://127.0.0.1/student/8mlVHdU5.aspx", the plugin sent grep=False.
GET http://127.0.0.1/student/3dEV8D7t.pl returned HTTP code "403" - id: 15
GET http://127.0.0.1/student/OUUivLqI.xhtml returned HTTP code "403" - id: 14
No grep for: "http://127.0.0.1/student/OUUivLqI.xhtml", the plugin sent grep=False.
No grep for: "http://127.0.0.1/student/3dEV8D7t.pl", the plugin sent grep=False.
The 404 body result database has a length of 1.
"http://127.0.0.1/student/" (id:1) is a 404 [similarity_index > 0.9]
Called _discover_worker()
Starting plugin: webSpider
webSpider plugin is testing: http://127.0.0.1/student/
GET http://127.0.0.1/student/ returned HTTP code "403" - id: 16
[thread manager] Successfully added function to threadpool. Work queue size: 1
[thread manager] Successfully added function to threadpool. Work queue size: 2
GET http://127.0.0.1/student/ returned HTTP code "403" - id: 17
"http://127.0.0.1/student/" (id:17) is a 404 [similarity_index > 0.9]
GET http://127.0.0.1/ returned HTTP code "403" - id: 18
"http://127.0.0.1/" (id:18) is a 404 [similarity_index > 0.9]
The following is a list of broken links that were found by the webSpider plugin:

ModSecurity 模块开启后:

Exiting setOutputPlugins()
Called w3afCore.start()
Enabling _dnsCache()
Called buildOpeners
keepalive: added one connection, len(self._hostmap["127.0.0.1"]): 1
DNS response from DNS server for domain: 127.0.0.1
GET http://127.0.0.1/student/ returned HTTP code "403" - id: 1
[thread manager] Successfully added function to threadpool. Work queue size: 1
[thread manager] Successfully added function to threadpool. Work queue size: 2
[thread manager] Successfully added function to threadpool. Work queue size: 3
[thread manager] Successfully added function to threadpool. Work queue size: 4
[thread manager] Successfully added function to threadpool. Work queue size: 5
[thread manager] Successfully added function to threadpool. Work queue size: 6
[thread manager] Successfully added function to threadpool. Work queue size: 7
[thread manager] Successfully added function to threadpool. Work queue size: 8
[thread manager] Successfully added function to threadpool. Work queue size: 9
[thread manager] Successfully added function to threadpool. Work queue size: 10
[thread manager] Successfully added function to threadpool. Work queue size: 11
[thread manager] Successfully added function to threadpool. Work queue size: 12
[thread manager] Successfully added function to threadpool. Work queue size: 13
[thread manager] Successfully added function to threadpool. Work queue size: 14
keepalive: added one connection, len(self._hostmap["127.0.0.1"]): 2
Cached DNS response for domain: 127.0.0.1
keepalive: added one connection, len(self._hostmap["127.0.0.1"]): 3
keepalive: added one connection, len(self._hostmap["127.0.0.1"]): 4
Cached DNS response for domain: 127.0.0.1
Cached DNS response for domain: 127.0.0.1
GET http://127.0.0.1/student/Vg1vHrJO. returned HTTP code "403" - id: 2
No grep for: "http://127.0.0.1/student/Vg1vHrJO.", the plugin sent grep=False.
GET http://127.0.0.1/student/a2O3LyYI.do returned HTTP code "403" - id: 4
GET http://127.0.0.1/student/0eLnOV3J.asp returned HTTP code "403" - id: 3
No grep for: "http://127.0.0.1/student/a2O3LyYI.do", the plugin sent grep=False.
No grep for: "http://127.0.0.1/student/0eLnOV3J.asp", the plugin sent grep=False.
GET http://127.0.0.1/student/mAGEns7z.py returned HTTP code "403" - id: 6
No grep for: "http://127.0.0.1/student/mAGEns7z.py", the plugin sent grep=False.
GET http://127.0.0.1/student/khbMvzIG.htmls returned HTTP code "403" - id: 8
No grep for: "http://127.0.0.1/student/khbMvzIG.htmls", the plugin sent grep=False.
GET http://127.0.0.1/student/qMyT7lZ5.jsp returned HTTP code "403" - id: 9
GET http://127.0.0.1/student/SU7LbF3J.htm returned HTTP code "403" - id: 5
No grep for: "http://127.0.0.1/student/SU7LbF3J.htm", the plugin sent grep=False.
No grep for: "http://127.0.0.1/student/qMyT7lZ5.jsp", the plugin sent grep=False.
GET http://127.0.0.1/student/iJRJULzR.gif returned HTTP code "403" - id: 7
No grep for: "http://127.0.0.1/student/iJRJULzR.gif", the plugin sent grep=False.
GET http://127.0.0.1/student/jTrkFnpt.xhtml returned HTTP code "403" - id: 14
No grep for: "http://127.0.0.1/student/jTrkFnpt.xhtml", the plugin sent grep=False.
GET http://127.0.0.1/student/H0xoFI0S.cgi returned HTTP code "403" - id: 11
No grep for: "http://127.0.0.1/student/H0xoFI0S.cgi", the plugin sent grep=False.
GET http://127.0.0.1/student/lwzkMqkS.php returned HTTP code "403" - id: 13
No grep for: "http://127.0.0.1/student/lwzkMqkS.php", the plugin sent grep=False.
GET http://127.0.0.1/student/gW3XjZz8.rb returned HTTP code "403" - id: 10
No grep for: "http://127.0.0.1/student/gW3XjZz8.rb", the plugin sent grep=False.
GET http://127.0.0.1/student/zQ2qJZkl.aspx returned HTTP code "403" - id: 12
No grep for: "http://127.0.0.1/student/zQ2qJZkl.aspx", the plugin sent grep=False.
GET http://127.0.0.1/student/JAdleo2T.pl returned HTTP code "403" - id: 15
No grep for: "http://127.0.0.1/student/JAdleo2T.pl", the plugin sent grep=False.
The 404 body result database has a length of 1.
"http://127.0.0.1/student/" (id:1) is a 404 [similarity_index > 0.9]
Called _discover_worker()
Starting plugin: webSpider
webSpider plugin is testing: http://127.0.0.1/student/
GET http://127.0.0.1/student/ returned HTTP code "403" - id: 16
[thread manager] Successfully added function to threadpool. Work queue size: 1
[thread manager] Successfully added function to threadpool. Work queue size: 2
GET http://127.0.0.1/student/ returned HTTP code "403" - id: 17
"http://127.0.0.1/student/" (id:17) is a 404 [similarity_index > 0.9]
GET http://127.0.0.1/ returned HTTP code "403" - id: 18
"http://127.0.0.1/" (id:18) is a 404 [similarity_index > 0.9]
The following is a list of broken links that were found by the webSpider plugin:

图片.png
图片.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,922评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,591评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,546评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,467评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,553评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,580评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,588评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,334评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,780评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,092评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,270评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,925评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,573评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,194评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,437评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,154评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容

  • 班级:1518011 姓名:于沂渭 学号:151801100005 1. 测试网页已前置 Apache 2.安装并...
    不湿的尿布湿阅读 2,171评论 0 0
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,647评论 18 139
  • 班级:1518011 姓名:于沂渭 学号:151801100005 一.安装mysql 1.0首先查看是否安装my...
    不湿的尿布湿阅读 1,830评论 0 0
  • Scala是基于JVM的一种通用函数式也是面向对象编程语言,能和Java、C#等主流的编程语言无缝融合。下面给大家...
    lehi阅读 865评论 0 7
  • 没有反思的人生不值得过!越反思越进步,反思就像一根平衡线,随时调整方向! 本周收获特别特别大! 作为服装零售...
    娟子小絮阅读 347评论 1 2