码迷,mamicode.com
首页 > 其他好文 > 详细

实验:基本的系统安全控制

时间:2016-06-25 15:09:49      阅读:301      评论:0      收藏:0      [点我收藏+]

标签:配置grub密码;sudo;su;tty;基本系统安全控制

实验:基本的系统安全控制




实验环境


某公司新增了一台企业级服务器,已安装运行RHEL 6操作系统,由系统运维部、软件开发部、技术服务部共同使用。由于用户数量众多,且使用时间不固定,要求针对账号和登录过程采取基本的安全措施。


需求描述


  • 允许用户radmin使用su命令进行切换,其他用户一律禁止切换身份。

  • 授权用户zhangsan管理所有员工的账号,但禁止其修改root用户的信息。

  • 授权用户lisi能够执行/sbin、/usr/sbin目录下的所有特权命令,不需要密码验证。

  • 所有的su、sudo操作,必须在系统日志文件中进行记录。

  • 禁止使用Ctrl + Alt + Del快捷键,只开放tty3、tty5终端,为GRUB引导菜单设置密码。




允许用户radmin使用su命令进行切换,其他用户一律禁止切换身份


配置

  • vi /etc/pam.d/su

技术分享


  • 取消注释,以生效wheel组

技术分享


  • 添加用户radmin

[root@test2 jason]# useradd -g wheel radmin
[root@test2 jason]# passwd radmin
Changing password for user radmin.
New password: 
BAD PASSWORD: it does not contain enough DIFFERENT characters
BAD PASSWORD: is too simple
Retype new password: 
passwd: all authentication tokens updated successfully.

创建radmin的同时,指定radmin的基本组是wheel


  • 查看属组等信息:

[root@test2 jason]# id radmin
uid=509(radmin) gid=10(wheel) groups=10(wheel)

这里能看出来在wheel的组内


  • 查看wheel组信息:

[root@test2 jason]# cat /etc/group | grep wheel
wheel:x:10:xiao

这里有一个xiao用户,根据要求只能有radmin,所以删除这个组


  • 从wheel组当中删除xiao

[root@test2 jason]# gpasswd -d xiao wheel
Removing user xiao from group wheel


  • 查看删除后的结果

[root@test2 jason]# cat /etc/group | grep wheel
wheel:x:10:

可以看到wheel组当中已经没有了xiao这个用户


测试


1.radmin是否可以使用su命令进行切换

[root@test2 jason]# su radmin
[radmin@test2 jason]$ su
Password: 
[root@test2 jason]#

这里可以看出来从radmin切换到root的时候是可以执行的。


2.非radmin用户是否可以使用su命令进行切换

[root@test2 jason]# su jason
[jason@test2 ~]$ su
Password: 
su: incorrect password
[jason@test2 ~]$ exit
exit
[root@test2 jason]# su xiao
[xiao@test2 jason]$ su
Password: 
su: incorrect password

从这里可以看出来当jason和xiao两个用户在使用su的时候是无法切换的。




授权用户zhangsan管理所有员工的账号,但禁止其修改root用户的信息。


配置

  • visudo

[root@test2 bin]# visudo

## Sudoers allows particular users to run various commands as
## the root user, without needing the root password.
##
## Examples are provided at the bottom of the file for collections
## of related commands, which can then be delegated out to particular
## users or groups.
## 
## This file must be edited with the ‘visudo‘ command.

## Host Aliases
## Groups of machines. You may prefer to use hostnames (perhaps using 
## wildcards for entire domains) or IP addresses instead.
# Host_Alias FILESERVERS = fs1, fs2
# Host_Alias MAILSERVERS = smtp, smtp2

## User Aliases
## These aren‘t often necessary, as you can use regular groups
## (ie, from files, LDAP, NIS, etc) in this file - just use %groupname 
## rather than USERALIAS
# User_Alias ADMINS = jsmith, mikem


## Command Aliases
## These are groups of related commands...

## Networking

## Installation and management of software
# Cmnd_Alias SOFTWARE = /bin/rpm, /usr/bin/up2date, /usr/bin/yum

## Services
# Cmnd_Alias SERVICES = /sbin/service, /sbin/chkconfig

## Updating the locate database
# Cmnd_Alias LOCATE = /usr/bin/updatedb

## Storage
# Cmnd_Alias STORAGE = /sbin/fdisk, /sbin/sfdisk, /sbin/parted, /sbin/partprobe, /bin/mount, /bin/umount

## Delegating permissions
# Cmnd_Alias DELEGATING = /usr/sbin/visudo, /bin/chown, /bin/chmod, /bin/chgrp 

## Processes
# Cmnd_Alias PROCESSES = /bin/nice, /bin/kill, /usr/bin/kill, /usr/bin/killall

## Drivers
# Cmnd_Alias DRIVERS = /sbin/modprobe

# Defaults specification

#
# Disable "ssh hostname sudo <cmd>", because it will show the password in clear.
# You have to run "ssh -t hostname sudo <cmd>".
#
Defaultsrequiretty

#
# Refuse to run if unable to disable echo on the tty. This setting should also be
# changed in order to be able to use sudo without a tty. See requiretty above.
#
Defaults   !visiblepw

#
# Preserving HOME has security implications since many programs
# use it when searching for configuration files. Note that HOME
# is already set when the the env_reset option is enabled, so
# this option is only effective for configurations where either
# env_reset is disabled or HOME is present in the env_keep list.
#
Defaultsalways_set_home

Defaultsenv_reset
Defaultsenv_keep =  "COLORS DISPLAY HOSTNAME HISTSIZE INPUTRC KDEDIR LS_COLORS"
Defaultsenv_keep += "MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE"
Defaultsenv_keep += "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES"
Defaultsenv_keep += "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE"
Defaultsenv_keep += "LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY"

#
# Adding HOME to env_keep may enable a user to run unrestricted
# commands via sudo.
#
# Defaults   env_keep += "HOME"

Defaultssecure_path = /sbin:/bin:/usr/sbin:/usr/bin

## Next comes the main part: which users can run what software on 
## which machines (the sudoers file can be shared between multiple
## systems).
## Syntax:
##
## The COMMANDS section may have other options added to it.
##
## Allow root to run any commands anywhere 
rootALL=(ALL)   ALL

## Allows members of the ‘sys‘ group to run networking, software, 
## service management apps and more.
# %sys ALL = NETWORKING, SOFTWARE, SERVICES, STORAGE, DELEGATING, PROCESSES, LOCATE, DRIVERS

## Allows people in group wheel to run all commands
# %wheelALL=(ALL)   ALL

## Same thing without a password
# %wheelALL=(ALL)   NOPASSWD: ALL

## Allows members of the users group to mount and unmount the 
## cdrom as root
# %users  ALL=/sbin/mount /mnt/cdrom, /sbin/umount /mnt/cdrom

## Allows members of the users group to shutdown this system
# %users  localhost=/sbin/shutdown -h now

## Read drop-in files from /etc/sudoers.d (the # here does not mean a comment)
#includedir /etc/sudoers.d
zhangsan test2=/usr/sbin/useradd,/usr/sbin/userdel,/usr/sbin/usermod,/usr/bin/passwd,!/usr/bin/passwd root ,!/usr/sbin/usermod root
-- INSERT --

在结尾的地方加入zhangsan test2=/usr/sbin/useradd,/usr/sbin/userdel,/usr/sbin/usermod,/usr/bin/passwd,!/usr/bin/passwd root ,!/usr/sbin/usermod root


测试


1.zhangsan管理其他用户

  • 更改密码

[zhangsan@test2 bin]$ sudo passwd obama
[sudo] password for zhangsan: 
Changing password for user obama.
New password: 
BAD PASSWORD: it does not contain enough DIFFERENT characters
BAD PASSWORD: is too simple
Retype new password: 
passwd: all authentication tokens updated successfully.
  • 通过usermod锁定和解锁

[zhangsan@test2 jason]$ sudo usermod -L kylin
[sudo] password for zhangsan: 
[zhangsan@test2 jason]$ tail /etc/shadow | grep kylin
tail: cannot open `/etc/shadow‘ for reading: Permission denied
[zhangsan@test2 jason]$ sudo tail /etc/shadow | grep kylin
Sorry, user zhangsan is not allowed to execute ‘/usr/bin/tail /etc/shadow‘ as root on test2.       `//因为前面在visudo的时候并没有给/usr/bin/tail权限,所以不能执行`
[zhangsan@test2 jason]$ su                                //切换回root用户
Password: 
[root@test2 jason]# tail /etc/shadow | grep kylkin
[root@test2 jason]# tail /etc/shadow | grep kylin
kylin:!!:16976:0:60:7:::                                 //kylin后面有两个!!,表示已经锁定
[root@test2 jason]# su zhangsan
[zhangsan@test2 jason]$ sudo usermod -U kylin
[zhangsan@test2 jason]$ su
Password: 
[root@test2 jason]# tail /etc/shadow | grep kylin
kylin:!:16976:0:60:7:::                                  //这里可以看到只有一个!,表示通过zhangsan账户已经解锁了kylin账户
  • 删除用户

[zhangsan@test2 jason]$ tail /etc/passwd | grep kylin
kylin:x:511:511::/home/kylin:/bin/bash         //查看有kylin这个用户
[zhangsan@test2 jason]$ sudo userdel -r kylin  //删除kylin用户
[sudo] password for zhangsan: 
userdel: /var/spool/mail/kylin not owned by kylin, not removing
[zhangsan@test2 jason]$ tail /etc/passwd | grep kylin    //再次查看kylin用户
[zhangsan@test2 jason]$                        //没有查找到结果,说明已经删除成功
  • 增加用户

[zhangsan@test2 bin]$ sudo useradd ubuntu   //增加用户ubuntu
[zhangsan@test2 bin]$ sudo passwd ubuntu    //设置ubuntu密码
Changing password for user ubuntu.
New password: 
BAD PASSWORD: it does not contain enough DIFFERENT characters
BAD PASSWORD: is too simple
Retype new password: 
passwd: all authentication tokens updated successfully.
[zhangsan@test2 bin]$ tail -1 /etc/passwd   //查看ubuntu
ubuntu:x:512:512::/home/ubuntu:/bin/bash    //查找到ubuntu

2.zhangsan对root的修改的权限:

[zhangsan@test2 bin]$ sudo passwd root
Sorry, user zhangsan is not allowed to execute ‘/usr/bin/passwd root‘ as root on test2.  //显示zhagnsan不被允许执行‘/usr/bin passwd root‘
[zhangsan@test2 bin]$ sudo usermod root
Sorry, user zhangsan is not allowed to execute ‘/usr/sbin/usermod root‘ as root on test2.  //提示zhangsan无法执行‘/usr/bin/usermod root‘




授权用户lisi能够执行/sbin、/usr/sbin目录下的所有特权命令,不需要密码验证。


  • 创建lisi用户

[root@test2 jason]# useradd lisi
[root@test2 jason]# passwd lisi
Changing password for user lisi.
New password: 
BAD PASSWORD: it does not contain enough DIFFERENT characters
BAD PASSWORD: is too simple
Retype new password: 
passwd: all authentication tokens updated successfully.
[root@test2 jason]# tail -1 /etc/passwd
lisi:x:513:513::/home/lisi:/bin/bash
[root@test2 jason]#
  • 设置sudo权限范围

[root@test2 jason]# visudo
...
...
...//这里省略了前面的部分
## The COMMANDS section may have other options added to it.
##
## Allow root to run any commands anywhere
root    ALL=(ALL)       ALL

## Allows members of the ‘sys‘ group to run networking, software,
## service management apps and more.
# %sys ALL = NETWORKING, SOFTWARE, SERVICES, STORAGE, DELEGATING, PROCESSES, LOCATE, DRIVERS

## Allows people in group wheel to run all commands
# %wheel        ALL=(ALL)       ALL

## Same thing without a password
# %wheel        ALL=(ALL)       NOPASSWD: ALL

## Allows members of the users group to mount and unmount the
## cdrom as root
# %users  ALL=/sbin/mount /mnt/cdrom, /sbin/umount /mnt/cdrom

## Allows members of the users group to shutdown this system
# %users  localhost=/sbin/shutdown -h now

## Read drop-in files from /etc/sudoers.d (the # here does not mean a comment)
#includedir /etc/sudoers.d
zhangsan test2=/usr/sbin/useradd,/usr/sbin/userdel,/usr/sbin/usermod,/usr/bin/passwd,!/usr/bin/passwd root ,!/usr/sbin/usermod root
lisi test2=/sbin/*,/usr/sbin/*     //在最后一行加入本行的内容。‘/sbin/#‘代表sbin目录下的所有。‘/usr/sbin/*‘是一样的作用。

:wq
  • 从sbin中找一个来测试

[lisi@test2 sbin]$ sudo pvscan

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

[sudo] password for lisi:    //这里输入密码后,就会执行pvscan的操作,而下面的内容则是pvscan的结果
  PV /dev/sdb2   VG mail_store      lvm2 [20.01 GiB / 0    free]
  PV /dev/sdc2   VG mail_store      lvm2 [20.01 GiB / 0    free]
  PV /dev/sdd1   VG mail_store      lvm2 [100.00 GiB / 20.01 GiB free]
  PV /dev/sda2   VG vg_jason        lvm2 [19.51 GiB / 0    free]
  PV /dev/sdb1                      lvm2 [20.01 GiB]
  Total: 5 [179.53 GiB] / in use: 4 [159.52 GiB] / in no VG: 1 [20.01 GiB]
[lisi@test2 sbin]$
  • 从/usr/sbin中找一个测试

[lisi@test2 sbin]$ pwd
/usr/sbin
[lisi@test2 sbin]$ ls | grep quotastats   
quotastats                              //在/usr/bin/下面有quotastats的命令
[lisi@test2 sbin]$ sudo quotastats      //用sudo来执行该命令
Kernel quota version: 6.5.1             //下面的结果中展示了当前磁盘配额的信息。
Number of dquot lookups: 0
Number of dquot drops: 0
Number of dquot reads: 0
Number of dquot writes: 0
Number of quotafile syncs: 12
Number of dquot cache hits: 0
Number of allocated dquots: 0
Number of free dquots: 0
Number of in use dquot entries (user/group): 0
[lisi@test2 sbin]$




所有的su、sudo操作,必须在系统日志文件中进行记录。


  • visudo

[root@test2 sbin]# visudo

## Sudoers allows particular users to run various commands as
## the root user, without needing the root password.
##
## Examples are provided at the bottom of the file for collections
## of related commands, which can then be delegated out to particular
## users or groups.
##
## This file must be edited with the ‘visudo‘ command.

## Host Aliases
## Groups of machines. You may prefer to use hostnames (perhaps using
## wildcards for entire domains) or IP addresses instead.
# Host_Alias     FILESERVERS = fs1, fs2
# Host_Alias     MAILSERVERS = smtp, smtp2

## User Aliases
## These aren‘t often necessary, as you can use regular groups
## (ie, from files, LDAP, NIS, etc) in this file - just use %groupname
## rather than USERALIAS
# User_Alias ADMINS = jsmith, mikem


## Command Aliases
## These are groups of related commands...

## Networking

## Installation and management of software
# Cmnd_Alias SOFTWARE = /bin/rpm, /usr/bin/up2date, /usr/bin/yum

## Services
# Cmnd_Alias SERVICES = /sbin/service, /sbin/chkconfig

## Updating the locate database
# Cmnd_Alias LOCATE = /usr/bin/updatedb

## Storage
# Cmnd_Alias STORAGE = /sbin/fdisk, /sbin/sfdisk, /sbin/parted, /sbin/partprobe, /bin/mount, /bin/umount

## Delegating permissions
# Cmnd_Alias DELEGATING = /usr/sbin/visudo, /bin/chown, /bin/chmod, /bin/chgrp

## Processes
# Cmnd_Alias PROCESSES = /bin/nice, /bin/kill, /usr/bin/kill, /usr/bin/killall

## Drivers
# Cmnd_Alias DRIVERS = /sbin/modprobe

# Defaults specification

#
# Disable "ssh hostname sudo <cmd>", because it will show the password in clear.
#         You have to run "ssh -t hostname sudo <cmd>".
#
Defaults    requiretty

#
# Refuse to run if unable to disable echo on the tty. This setting should also be
# changed in order to be able to use sudo without a tty. See requiretty above.
#
Defaults   !visiblepw

#
# Preserving HOME has security implications since many programs
# use it when searching for configuration files. Note that HOME
# is already set when the the env_reset option is enabled, so
# this option is only effective for configurations where either
# env_reset is disabled or HOME is present in the env_keep list.
#
Defaults    always_set_home

Defaults    env_reset
Defaults    env_keep =  "COLORS DISPLAY HOSTNAME HISTSIZE INPUTRC KDEDIR LS_COLORS"
Defaults    env_keep += "MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE"
Defaults    env_keep += "LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES"
Defaults    env_keep += "LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE"
Defaults    env_keep += "LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY"

#
# Adding HOME to env_keep may enable a user to run unrestricted
# commands via sudo.
#
# Defaults   env_keep += "HOME"

Defaults    secure_path = /sbin:/bin:/usr/sbin:/usr/bin

## Next comes the main part: which users can run what software on
## which machines (the sudoers file can be shared between multiple
## systems).
## Syntax:
##
## The COMMANDS section may have other options added to it.
##
## Allow root to run any commands anywhere
root    ALL=(ALL)       ALL

## Allows members of the ‘sys‘ group to run networking, software,
## service management apps and more.
# %sys ALL = NETWORKING, SOFTWARE, SERVICES, STORAGE, DELEGATING, PROCESSES, LOCATE, DRIVERS

## Allows people in group wheel to run all commands
# %wheel        ALL=(ALL)       ALL

## Same thing without a password
# %wheel        ALL=(ALL)       NOPASSWD: ALL

## Allows members of the users group to mount and unmount the
## cdrom as root
# %users  ALL=/sbin/mount /mnt/cdrom, /sbin/umount /mnt/cdrom

## Allows members of the users group to shutdown this system
# %users  localhost=/sbin/shutdown -h now

## Read drop-in files from /etc/sudoers.d (the # here does not mean a comment)
#includedir /etc/sudoers.d
zhangsan test2=/usr/sbin/useradd,/usr/sbin/userdel,/usr/sbin/usermod,/usr/bin/passwd,!/usr/bin/passwd root ,!/usr/sbin/usermod root
lisi test2=/sbin/*,/usr/sbin/*
Defaults logfile=/var/log/sudo   
:wq

在最后一行加入Defaults logfile=/var/log/sudo,这样所有的su、sudo操作都会记录在/var/log/sudo的文件当中


  • 简单测试

[zhangsan@test2 sbin]$ sudo fdisk -l
[sudo] password for zhangsan: 
Sorry, user zhangsan is not allowed to execute ‘/sbin/fdisk -l‘ as root on test2.
[zhangsan@test2 sbin]$ sudo useradd kylin
[sudo] password for zhangsan: 
Creating mailbox file: File exists
[zhangsan@test2 sbin]$ su
Password: 
[root@test2 sbin]# tail /var/log/sudo  //查看/var/log下的sudo文件内容
Jun 25 09:43:14 : zhangsan : command not allowed ; TTY=pts/0 ; PWD=/usr/sbin ;
    USER=root ; COMMAND=/sbin/fdisk -l                                    //这记录的是上面zhangsan使用sudo fdisk -l时候的信息
Jun 25 09:43:39 : zhangsan : TTY=pts/0 ; PWD=/usr/sbin ; USER=root ;
    COMMAND=/usr/sbin/useradd kylin                                       //这里揭露的是增加用户kylin时候的信息。
[root@test2 sbin]#




禁止使用Ctrl + Alt + Del快捷键,


  • vi /etc/init/control-alt-delete

[root@test2 sysconfig]# vi /etc/init/control-alt-delete.conf 

# control-alt-delete - emergency keypress handling
#
# This task is run whenever the Control-Alt-Delete key combination is
# pressed.  Usually used to shut down the machine.
#
# Do not edit this file directly. If you want to change the behaviour,
# please create a file control-alt-delete.override and put your changes there.

#start on control-alt-delete

#exec /sbin/shutdown -r now "Control-Alt-Delete pressed"
~                                                                                                       
~                                                                                                       
~                                                                                                       
~                                                                                                       
~                                                                                                       
~                                                                                                       
~                                                                                                       
~                                                                                                       
~                                                                                                       
~                                                                                                       
~                                                                                                       
~                                                                                                       
~                                                                                                       
~                                                                                                       
~                                                                                                       
~                                                                                                       
:wq


技术分享


技术分享




只开放tty3、tty5终端


  • vi /etc/init/start-ttys.conf

[root@test2 sysconfig]# vi /etc/init/start-ttys.conf 

#
# This service starts the configured number of gettys.
#
# Do not edit this file directly. If you want to change the behaviour,
# please create a file start-ttys.override and put your changes there.

start on stopped rc RUNLEVEL=[2345]

env ACTIVE_CONSOLES=/dev/tty[35]
env X_TTY=/dev/tty1
task
script
        . /etc/sysconfig/init
        for tty in $(echo $ACTIVE_CONSOLES) ; do
                [ "$RUNLEVEL" = "5" -a "$tty" = "$X_TTY" ] && continue
                initctl start tty TTY=$tty
        done
end script
~                                                                                                       
~                                                                                                       
~                                                                                                       
~                                                                                                       
~                                                                                                       
~                                                                                                       
~                                                                                                       
~                                                                                                       
~                                                                                                       
:wq


技术分享


  • vi /etc/sysconfig/init

[root@test2 sysconfig]# vi /etc/sysconfig/init 

# color => new RH6.0 bootup
# verbose => old-style bootup
# anything else => new style bootup without ANSI colors or positioning
BOOTUP=color
# column to start "[  OK  ]" label in 
RES_COL=60
# terminal sequence to move to that column. You could change this
# to something like "tput hpa ${RES_COL}" if your terminal supports it
MOVE_TO_COL="echo -en \\033[${RES_COL}G"
# terminal sequence to set color to a ‘success‘ color (currently: green)
SETCOLOR_SUCCESS="echo -en \\033[0;32m"
# terminal sequence to set color to a ‘failure‘ color (currently: red)
SETCOLOR_FAILURE="echo -en \\033[0;31m"
# terminal sequence to set color to a ‘warning‘ color (currently: yellow)
SETCOLOR_WARNING="echo -en \\033[0;33m"
# terminal sequence to reset to the default color.
SETCOLOR_NORMAL="echo -en \\033[0;39m"
# Set to anything other than ‘no‘ to allow hotkey interactive startup...
PROMPT=yes
# Set to ‘yes‘ to allow probing for devices with swap signatures
AUTOSWAP=no
# What ttys should gettys be started on?
ACTIVE_CONSOLES=/dev/tty[35]
# Set to ‘/sbin/sulogin‘ to prompt for password on single-user mode
# Set to ‘/sbin/sushell‘ otherwise
SINGLE=/sbin/sushell
~                                                                                                       
:wq


技术分享


测试


  • Alt+F5

技术分享


  • Alt+F3

技术分享


  • Alt+F1

技术分享


  • Alt+F2

技术分享


  • Alt+F4、F6都没有任何的反应

没有实现预料中的Alt+F3切换到tty3,Alt+F5切换到tty5。




为GRUB引导菜单设置密码


  • grub-mdf-crypt

技术分享


  • vi /boot/grub/grub.conf

技术分享


测试

  • 重启

测试发现没有效果,分析,是自己的格式写的有问题,应该是password —md5 …而不是passwd

重新修改


技术分享


  • 再次重启

技术分享


技术分享


技术分享


技术分享


技术分享


  • 密码配置生效




本文出自 “Code Life” 博客,请务必保留此出处http://zencode.blog.51cto.com/11714065/1792822

实验:基本的系统安全控制

标签:配置grub密码;sudo;su;tty;基本系统安全控制

原文地址:http://zencode.blog.51cto.com/11714065/1792822

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!