分类 技术 下的文章

刚开始学习软件工程的时候,我们经常会碰到像这样的事情:

软件应该符合 SOLID 原则。

但这句话实际是什么意思?让我们看看 SOLID 中每个字母在架构里所代表的重要含义,例如:

简单来说,我们需要提供一个类,这个类有它所需要的所有对象,以便实现其功能。

概述

依赖注入听起来像是描述非常复杂的东西的一个术语,但实际上它很简单,看下面这个例子你就明白了:

class NoDependencyInjection {
  private Dependency d;

  public NoDependencyInjection() {
    d = new Dependency();
  }
}

class DependencyInjection {
  private Dependency d;

  public DependencyInjection(Dependency d) {
    this.d = d;
  }
}

正如我们所见,第一种情况是我们在构造器里创建了依赖对象,但在第二种情况下,它作为参数被传递给构造器,这就是我们所说的 依赖注入 dependency injection 。这样做是为了让我们所写的类不依靠特定依赖关系的实现,却能直接使用它。

参数传递的目标是构造器,我们就称之为构造器依赖注入;或者是某个方法,就称之为方法依赖注入:

class Example {
  private ConstructorDependency cd;
  private MethodDependency md;
  Example(ConstructorDependency cd) {
    this.cd = cd; //Constructor Dependency Injection
  }

  public setMethodDependency(MethodDependency md) {
    this.md = md; //Method Dependency Injection
  }
}

要是你想总体深入地了解依赖注入,可以看看由 Dan Lew 发表的精彩的演讲,事实上是这个演讲启迪了这篇概述。

在 Android 平台,当需要框架来处理依赖注入这个特殊的问题时,我们有不同的选择,其中最有名的框架就是 Dagger 2。它最开始是由 Square 公司(LCTT 译注:Square 是美国一家移动支付公司)的一些很棒的开发者开发出来的,然后慢慢发展成由 Google 自己开发。首先开发出来的是 Dagger 1,然后 Big G 接手这个项目发布了第二个版本,做了很多改动,比如以 注解 annotation 为基础,在编译的时候完成其任务。

导入框架

安装 Dagger 并不难,但需要导入 android-apt 插件,通过向项目的根目录下的 build.gradle 文件中添加它的依赖关系:

buildscript{
  ...
  dependencies{
    ...
    classpath ‘com.neenbedankt.gradle.plugins:android-apt:1.8’
  }
}

然后,我们需要将 android-apt 插件应用到项目 build.gradle 文件,放在文件顶部 Android application 那一句的下一行:

apply plugin: ‘com.neenbedankt.android-apt’

这个时候,我们只用添加依赖关系,然后就能使用库及其 注解 annotation 了:

dependencies{
    ...
    compile ‘com.google.dagger:dagger:2.6’ 
    apt ‘com.google.dagger:dagger-compiler:2.6’
    provided ‘javax.annotation:jsr250-api:1.0’
}
需要加上最后一个依赖关系是因为 @Generated 注解在 Android 里还不可用,但它是原生的 Java 注解

Dagger 模块

要注入依赖,首先需要告诉框架我们能提供什么(比如说上下文)以及特定的对象应该怎样创建。为了完成注入,我们用 @Module 注释对一个特殊的类进行了注解(这样 Dagger 就能识别它了),寻找 @Provide 注解的方法,生成图表,能够返回我们所请求的对象。

看下面的例子,这里我们创建了一个模块,它会返回给我们 ConnectivityManager,所以我们要把 Context 对象传给这个模块的构造器。

@Module
public class ApplicationModule {
  private final Context context;

  public ApplicationModule(Context context) {
    this.context = context;
  }

  @Provides @Singleton
  public Context providesContext() {
    return context;
  }

  @Provides @Singleton
  public ConnectivityManager providesConnectivityManager(Context context) {
    return (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
  }
}
Dagger 中十分有意思的一点是简单地注解一个方法来提供一个单例(Singleton),就能处理所有从 Java 中继承过来的问题。

组件

当我们有一个模块的时候,我们需要告诉 Dagger 想把依赖注入到哪里:我们在一个 组件 Component 里完成依赖注入,这是一个我们特别创建的特殊注解接口。我们在这个接口里创造不同的方法,而接口的参数是我们想注入依赖关系的类。

下面给出一个例子并告诉 Dagger 我们想要 MainActivity 类能够接受 ConnectivityManager(或者在图表里的其它依赖对象)。我们只要做类似以下的事:

@Singleton
@Component(modules = {ApplicationModule.class})
public interface ApplicationComponent {

  void inject(MainActivity activity);
}
正如我们所见,@Component 注解有几个参数,一个是所支持的模块的数组,代表它能提供的依赖。这里既可以是 Context 也可以是 ConnectivityManager,因为它们在 ApplicationModule 类中有声明。

用法

这时,我们要做的是尽快创建组件(比如在应用的 onCreate 阶段)并返回它,那么类就能用它来注入依赖了:

为了让框架自动生成 DaggerApplicationComponent,我们需要构建项目以便 Dagger 能够扫描我们的代码,并生成我们需要的部分。

MainActivity 里,我们要做的两件事是用 @Inject 注解符对想要注入的属性进行注解,调用我们在 ApplicationComponent 接口中声明的方法(请注意后面一部分会因我们使用的注入类型的不同而变化,但这里简单起见我们不去管它),然后依赖就被注入了,我们就能自由使用他们:

public class MainActivity extends AppCompatActivity {
  @Inject
  ConnectivityManager manager;

  @Override
  protected void onCreate(Bundle savedInstanceState) {
    ...
    ((App) getApplication()).getComponent().inject(this);
  }
}

总结

当然了,我们可以手动注入依赖,管理所有不同的对象,但 Dagger 消除了很多比如模板这样的“噪声”,给我们提供有用的附加品(比如 Singleton),而仅用 Java 处理将会很糟糕。


via: https://medium.com/di-101/di-101-part-1-81896c2858a0#.3hg0jj14o

作者:Roberto Orgiu 译者:GitFuture 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

Samba 是一个自由的开源软件套件,用于实现 Windows 操作系统与 Linux/Unix 系统之间的无缝连接及共享资源。

Samba 不仅可以通过 SMB/CIFS 协议组件来为 Windows 与 Linux 系统之间提供独立的文件及打印机共享服务,它还能实现 活动目录 Active Directory 域控制器 Domain Controller 的功能,或者让 Linux 主机加入到域环境中作为域成员服务器。当前的 Samba4 版本实现的 AD DC 域及林功能级别可以取代 Windows 2008 R2 系统的域相关功能。

本系列的文章的主要内容是使用 Samba4 软件来配置活动目录域控制器,涉及到 Ubuntu、CentOS 和 Windows 系统相关的以下主题:

  • 第 1 节:在 Ubuntu 系统上使用 Samba4 来创建活动目录架构
  • 第 2 节:在 Linux 命令行下管理 Samba4 AD 架构
  • 第 3 节:在 Windows 10 操作系统上安装 RSAT 工具来管理 Samba4 AD
  • 第 4 节:从 Windows 中管理 Samba4 AD 域控制器 DNS 和组策略
  • 第 5 节:使用 Sysvol Replication 复制功能把 Samba 4 DC 加入到已有的 AD
  • 第 6 节:从 Linux DC 服务器通过 GOP 来添加一个共享磁盘并映射到 AD
  • 第 7 节:把 Ubuntu 16.04 系统主机作为域成员服务器添加到 AD
  • 第 8 节:把 CenterOS 7 系统主机作为域成员服务器添加到 AD
  • 第 9 节:在 AD Intranet 区域创建使用 kerberos 认证的 Apache Website

这篇指南将阐明在 Ubuntu 16.04 和 Ubuntu 14.04 操作系统上安装配置 Samba4 作为域控服务器组件的过程中,你需要注意的每一个步骤。

以下安装配置文档将会说明在 Windows 和 Linux 的混合系统环境中,关于用户、机器、共享卷、权限及其它资源信息的主要配置点。

环境要求:

  1. Ubuntu 16.04 服务器安装
  2. Ubuntu 14.04 服务器安装
  3. 为你的 AD DC 服务器设置静态IP地址

第一步:初始化 Samba4 安装环境

1、 在开始安装 Samba4 AD DC 之前,让我们先做一些准备工作。首先运行以下命令来确保系统已更新了最新的安全特性,内核及其它补丁:

$ sudo apt-get update 
$ sudo apt-get upgrade
$ sudo apt-get dist-upgrade

2、 其次,打开服务器上的 /etc/fstab 文件,确保文件系统分区的 ACL 已经启用 ,如下图所示。

通常情况下,当前常见的 Linux 文件系统,比如 ext3、ext4、xfs 或 btrfs 都默认支持并已经启用了 ACL 。如果未设置,则打开并编辑 /etc/fstab 文件,在第三列添加 acl,然后重启系统以使用修改的配置生效。

Enable ACL's on Linux Filesystem

启动 Linux 文件系统的 ACL 功能

3、 最后使用一个具有描述性的名称来设置主机名 ,比如这往篇文章所使用的 adc1。通过编辑 /etc/hostname 文件或使用使用下图所示的命令来设置主机名。

$ sudo hostnamectl set-hostname adc1

为了使修改的主机名生效必须重启服务器。

第二步: 为 Samba4 AD DC 服务器安装必需的软件包

4、 为了让你的服务器转变为域控制器,你需要在服务器上使用具有 root 权限的账号执行以下命令来安装 Samba 套件及所有必需的软件包。

$ sudo apt-get install samba krb5-user krb5-config winbind libpam-winbind libnss-winbind

Install Samba on Ubuntu

在 Ubuntu 系统上安装 Samba 套件

5、 安装包在执行的过程中将会询问你一系列的问题以便完成域控制器的配置。

在第一屏中你需要以大写为 Kerberos 默认 REALM 输入一个名字。以大写为你的域环境输入名字,然后单击回车继续。

Configuring Kerberos Authentication

配置 Kerosene 认证服务

6、 下一步,输入你的域中 Kerberos 服务器的主机名。使用和上面相同的名字,这一次使用小写,然后单击回车继续。

Set Hostname Kerberos Server

设置 Kerberos 服务器的主机名

7、 最后,指定 Kerberos realm 管理服务器的主机名。使用更上面相同的名字,单击回车安装完成。

Set Hostname Administrative Server

设置管理服务器的主机名

第三步:为你的域环境开启 Samba AD DC 服务

8、 在为域服务器配置 Samba 服务之前,先运行如下命令来停止并禁用所有 Samba 进程。

$ sudo systemctl stop samba-ad-dc.service smbd.service nmbd.service winbind.service
$ sudo systemctl disable samba-ad-dc.service smbd.service nmbd.service winbind.service

9、 下一步,重命名或删除 Samba 原始配置文件。在开启 Samba 服务之前,必须执行这一步操作,因为在开启服务的过程中 Samba 将会创建一个新的配置文件,如果检测到原有的 smb.conf 配置文件则会报错。

$ sudo mv /etc/samba/smb.conf /etc/samba/smb.conf.initial

10、 现在,使用 root 权限的账号并接受 Samba 提示的默认选项,以交互方式启动 域供给 domain provision

还有,输入正确的 DNS 服务器地址并且为 Administrator 账号设置强密码。如果使用的是弱密码,则域供给过程会失败。

$ sudo samba-tool domain provision --use-rfc2307 –interactive

Samba Domain Provisioning

Samba 域供给

11、 最后,使用以下命令重命名或删除 Kerberos 认证在 /etc 目录下的主配置文件,并且把 Samba 新生成的 Kerberos 配置文件创建一个软链接指向 /etc 目录。

$ sudo mv /etc/krb6.conf /etc/krb5.conf.initial
$ sudo ln –s /var/lib/samba/private/krb5.conf /etc/

Create Kerberos Configuration

创建 Kerberos 配置文件

12、 启动并开启 Samba 活动目录域控制器后台进程

$ sudo systemctl start samba-ad-dc.service
$ sudo systemctl status samba-ad-dc.service
$ sudo systemctl enable samba-ad-dc.service

Enable Samba Active Directory Domain Controller

开启 Samba 活动目录域控制器服务

13、 下一步,使用 netstat 命令 来验证活动目录启动的服务是否正常。

$ sudo netstat –tulpn| egrep ‘smbd|samba’

Verify Samba Active Directory

验证 Samba 活动目录

第四步: Samba 最后的配置

14、 此刻,Samba 应该跟你想像的一样,完全运行正常。Samba 现在实现的域功能级别可以完全跟 Windows AD DC 2008 R2 相媲美。

可以使用 samba-tool 工具来验证 Samba 服务是否正常:

$ sudo samba-tool domain level show

Verify Samba Domain Level

验证 Samba 域服务级别

15、 为了满足 DNS 本地解析的需求,你可以编辑网卡配置文件,修改 dns-nameservers 参数的值为域控制器地址(使用 127.0.0.1 作为本地 DNS 解析地址),并且设置 dns-search 参数为你的 realm 值。

$ sudo cat /etc/network/interfaces
$ sudo cat /etc/resolv.conf

Configure DNS for Samba AD

为 Samba 配置 DNS 服务器地址

设置完成后,重启服务器并检查解析文件是否指向正确的 DNS 服务器地址。

16、 最后,通过 ping 命令查询结果来检查某些重要的 AD DC 记录是否正常,使用类似下面的命令,替换对应的域名。

$ ping –c3 tecmint.lan       # 域名
$ ping –c3 adc1.tecmint.lan  # FQDN
$ ping –c3 adc1              # 主机

Check Samba AD DNS Records

检查 Samba AD DNS 记录

执行下面的一些查询命令来检查 Samba 活动目录域控制器是否正常。

$ host –t A tecmint.lan
$ host –t A adc1.tecmint.lan
$ host –t SRV _kerberos._udp.tecmint.lan  # UDP Kerberos SRV record
$ host -t SRV _ldap._tcp.tecmint.lan # TCP LDAP SRV record

17、 并且,通过请求一个域管理员账号的身份来列出缓存的票据信息以验证 Kerberos 认证是否正常。注意域名部分使用大写。

$ kinit [email protected]
$ klist

Check Kerberos Authentication on Domain

检查域环境中的 Kerberos 认证是否正确

至此! 你当前的网络环境中已经完全运行着一个 AD 域控制器,你现在可以把 Windows 或 Linux 系统的主机集成到 Samba AD 中了。

在下一期的文章中将会包括其它 Samba AD 域的主题,比如,在 Samba 命令行下如何管理你的域控制器,如何把 Windows 10 系统主机添加到同一个域环境中,如何使用 RSAT 工具远程管理 Samba AD 域,以及其它重要的主题。


via: http://www.tecmint.com/install-samba4-active-directory-ubuntu/

作者:Matei Cezar 译者:rusking 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

无论你使用的哪种 Linux 发行版,你都需要使用基于 iptables 的防火墙来保护它。

啊哈!你已经设置好了你的第一台 Linux 服务器并且已经准备发车了!是么?嗯,慢着。

默认情况下,你的 Linux 系统对攻击者来说并非是足够安全的。当然,它比 Windows XP 要安全多了,但这说明不了什么。

想要使你的 Linux 系统真正稳固,你需要按照 Linode服务器安全指南 来操作。

总的来说,首先你必须关闭那些你不需要的服务。当然要这样做的话,你先要知道你正在使用哪些网络服务。

你可以使用 shell 命令来找到是哪些服务:

netstat -tulpn

netstat 将会告诉你正在运行哪些服务和这些服务正在使用的端口是什么。如果你不需要其中的某项服务或端口,你就应该关闭它。例如,除非你正在运行一个网站,否则你是不需要运行中的 ApacheNginx 服务器,也不需要开启 80 或 8080 端口。

总之一句话,不确定的话,就关了它先。

在一个最简单的,没有做过任何额外更改的 Linux 服务器上,你会看到 SSHRPCNTPdate 运行在它们的公开端口上。不要添加像 telnet 这样陈旧而不安全的 shell 程序,否则老司机就会在你不经意间将你的 Linux 小跑车开走了。也许,在上世纪 80 年代的时候你喜欢把 telnet 当作你 SunOS 机器上的备份登录方式,但是那早已成为了过去。

就 SSH 来说,你应该使用 RSA 密钥Fail2Ban 来加固。除非你需要 RPC,否则就卸载它——如果你不知道需要不需要它的话,那就是不需要。

关于如何关门已经说的够多了;让我们来聊聊利用 iptables 来锁定进来的流量吧。

当你启动 Linux 服务器的时候它是没有任何规则的。这就意味着所有的流量都是被允许的。这当然是不好的。因此,你需要及时的设置你的防火墙。

Iptables 是一种用来给 netfilter 设置网络策略规则的 shell 工具,netfilter 是Linux 系统下的默认防火墙,它利用一组规则来允许或禁止流量。当有人尝试连接上你的系统——有些人无时不刻地尝试这么干,而且从不气馁——iptables 就会检查这些请求是否与规则列表相匹配。如果没有匹配到任何的规则,它就会采取默认操作。

这个默认操作应该是将连接“Drop”掉,即禁掉这些意图闯入者。而且这不会让他们知道这些网络探测行为发生了什么。(你也可以将链接“Reject”掉,但是这会同时让他们知道你有一个正在运行的 Linux 防火墙。就目前而言,让陌生人能获取到我们系统的信息越少越好。至少,我是这么认为的。)

现在,你可以用 iptables 来设置你的防火墙了。我已经这么做了。就像以前,我骑着自行车去六英里外上班,并且两边都是上坡。而现在,我开车去。

这其实比喻的是我使用 Fedora 发行版的 FirewallD 和 Debian 系发行版的 UFW(Uncomplicated Firewall)。这些都是易用的 iptables 的 shell 前端。你可以在以下的 Linode 指南中找到适合的使用方式:FirewallDUFW

从本质上来说设置这些规则就是在你的服务器上放置“非请勿入”的告示牌。用起来吧。

但是也别太兴奋地把所有的链接都关闭了。例如:

sudo ufw default deny incoming

看起来是个好主意哦。别忘了,它禁止了所有链接,包括你自己哦!

很好,它就是这么干的。这意味着它也同样禁止了 SSH 的登录。也就是说你再也不能登录你那新服务器了。哇哦!

不过,如果你犯了错,错误的将更多的链接都禁止了。你看,老司机也同样被你挡在门外了。

或者,更准确得说,这不是你或你的服务器所遇到的个别现象。当然,你也不是每天受到 3 亿多次攻击尝试的美国国家安全局(NSA)。但是攻击脚本根本不在乎你是谁。它只是不断的检查寻找网络中存在已知漏洞的服务器。在平常的一天中我自己的小服务器就会受到数以百计的攻击。

都这样了,你还在等什么呢?去吧,加固你的网络服务吧。安装 FirewallD 或者 UFW 来加固你的服务器吧。你会愿意去做的。


关于作者:

Steven J. Vaughan-Nichols 是一位资深的 IT 专栏作家,他的作品出现在许多行业领袖媒体上,包括 ZDNet.com、PC Magazine、InfoWorld、ComputerWorld、Linux Today 和 eWEEK 等。Steven 在 IT 专业方面的见解犀利,虽然他的观点和云计算方面的认识,并不代表 Linode 观点,但是我们仍然非常感谢他的贡献。你可以在 Twitter 上关注他 (@sjvn)。


via: https://medium.com/linode-cube/locking-down-your-linux-server-24d8516ae374#.qy8qq4bx2

作者:Steven J. Vaughan-Nichols 译者:wcnnbdk1 校对:wxy

本文由 LCTT 组织编译,Linux中国 荣誉推出

之前已经说过,一些最优秀的系统管理员看上去(注意这里使用的词是 seem(看上去))总是很“懒”的,这句话我再同意不过了。

虽然这句话听起来有点荒谬,但我敢打赌在大多数情况下它是对的-不是因为他们不去做他们原本应该做的事情,而是因为他们已经让系统自动去完成这样的事情了。

对于 Linux 系统来说,一个最关键的需求是为相应的 Linux 版本保持更新最新的安全补丁。

在这篇文章中,我们将讨论如何在 Debian 和 Ubuntu 系统上进行设置,从而实现自动安装或更新重要的安装包或补丁。

其他的 Linux 版本:CentOS/RHEL 配置自动安装安全更新

不必多说,为了执行这篇文章中所讲到的任务,你需要有超级用户特权。

在 Debian/Ubuntu 上配置自动安全更新

首先,安装下面这些安装包:

# aptitude update -y && aptitude install unattended-upgrades apt-listchanges -y

apt-listchanges 将会通知你在升级过程中发生的改变。

接下来,用你最喜欢的文本编辑器打开 /etc/apt/apt.conf.d/50unattended-upgrades,然后在 Unattended-Upgrade::Origins-Pattern 块中间加入下面这行内容:

Unattended-Upgrade::Mail "root";

最后,执行下面的命令来生成所需的配置文件(/etc/apt/apt.conf.d/20auto-upgrades),从而激活自动更新:

# dpkg-reconfigure -plow unattended-upgrades

当提示安装自动升级时,选择 'Yes':

在 Debian 上配置自动安装更新

在 Debian 上配置自动安装更新

然后检查下面这两行是否已经加入到文件 /etc/apt/apt.conf.d/20auto-upgrades 中了:

APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";

增加下面这行内容使通知更加详细:

APT::Periodic::Verbose "2";

最后,检查 /etc/apt/listchanges.conf 来确保通知能被发送给 root 用户。

Debian 系统上提示安全更新

在 Debian 系统上提示安全更新

在这篇文章中,我们讨论了如何确保你的系统定期更新最新的安全补丁。另外,你也学习了如何设置提示,从而确保应用了新的补丁时你能够被通知到。

你有任何关于这篇文章的问题吗?你可以在下面的评论栏留下你的问题。我们期待收到你的回复。


via: http://www.tecmint.com/auto-install-security-updates-on-debian-and-ubuntu

作者:Gabriel Cánepa 译者:ucasFL 校对:wxy

本文由 LCTT 组织编译,Linux中国 荣誉推出

Webpack 2 一旦文档完成,就将结束 Beta 测试期。不过这并不意味着你现在不能开始使用第 2 版,前提是你知道怎么配置它。(LCTT 译注:Webpack 2.1 已经发布。)

Webpack 是什么

简单来说,Webpack 是一个 JavaScript 模块打包器。然而,自从它发布以来,它发展成为了你所有的前端代码的管理工具(或许是有意的,或许是社区的意愿)。

老式的任务运行器的方式:你的标记、样式和 JavaScript 是分离的。你必须分别管理它们每一个,并且你需要确保每一样都达到产品级

任务运行器 task runner ,例如 Gulp,可以处理许多不同的 预处理器 preprocesser 转换器 transpiler ,但是在所有的情景下,它都需要一个输入源并将其压缩到一个编译好的输出文件中。然而,它是在每个部分的基础上这样做的,而没有考虑到整个系统。这就造成了开发者的负担:找到任务运行器所不能处理的地方,并找到适当的方式将所有这些模块在生产环境中联合在一起。

Webpack 试图通过提出一个大胆的想法来减轻开发者的负担:如果有一部分开发过程可以自动处理依赖关系会怎样?如果我们可以简单地写代码,让构建过程最终只根据需求管理自己会怎样?

Webpack 的方式:如果 Webpack 了解依赖关系,它会仅捆绑我们在生产环境中实际需要的部分

如果你过去几年一直参与 web 社区,你已经知道解决问题的首选方法:使用 JavaScript 来构建。而且 Webpack 尝试通过 JavaScript 传递依赖关系使得构建过程更加容易。不过这个设计真正的亮点不是简化代码管理部分,而是管理层由 100% 有效的 JavaScript 实现(具有 Nodejs 特性)。Webpack 能够让你编写有效的 JavaScript,更好更全面地了解系统。

换句话来说:你不需要为 Webpack 写代码。你只需要写项目代码。而且 Webpack 就会持续工作(当然需要一些配置)。

简而言之,如果你曾经遇到过以下任何一种情况:

  • 载入有问题的依赖项
  • 意外引入一些你不需要在生产中用上的 CSS 样式表和 JS 库,使项目膨胀
  • 意外的两次载入(或三次)库
  • 遇到作用域的问题 —— CSS 和 JavaScript 都会有
  • 寻找一个让你在 JavaScript 中使用 Node/Bower 模块的构建系统,要么就得依靠一个令人发狂的后端配置才能正确地使用这些模块
  • 需要优化 资产 asset 交付,但你担心会弄坏一些东西

等等……

那么你可以从 Webpack 中收益了。它通过让 JavaScript 轻松处理你的依赖关系和加载顺序,而不是通过开发者的大脑。最好的部分是,Webpack 甚至可以纯粹在服务器端运行,这意味着你还可以使用 Webpack 构建渐进增强式网站。

第一步

我们将在本教程中使用 Yarn(运行命令 brew install yarn) 代替 npm,不过这完全取决于你的喜好,它们做同样的事情。在我们的项目文件夹中,我们将在终端窗口中运行以下代码,将 Webpack 2 添加到我们的全局软件包以及本地项目中:

yarn global add [email protected] [email protected]
yarn add --dev [email protected] [email protected]

我们接着会通过项目根目录的一个 webpack.config.js 文件来声明 webpack 的配置:

'use strict';

const webpack = require('webpack');

module.exports = {
  context: __dirname + '/src',
  entry: {
    app: './app.js',
  },
  output: {
    path: __dirname + '/dist',
    filename: '[name].bundle.js',
  },
};

注意:此处 __dirname 是指你的项目根目录

记住,Webpack “知道”你的项目发生了什么。它通过阅读你的代码来实现(别担心,它签署了保密协议 :D )。Webpack 基本上执行以下操作:

  1. context 文件夹开始……
  2. ……它查找 entry 下的文件名……
  3. ……并读取其内容。每一个 importES6)或 require()(Nodejs)的依赖会在它解析代码的时候找到,它会在最终构建的时候打包这些依赖项。然后,它会搜索那些依赖项以及那些依赖项所依赖的依赖项,直到它到达“树”的最底端 —— 只打包它所需要的,没有其它东西。
  4. Webpack 从 context 文件夹打包所有东西到 output.path 文件夹,使用 output.filename 命名模板来为其命名(其中 [name] 被替换成来自 entry 的对象的键)。

所以如果我们的 src/app.js 文件看起来像这样(假设我们事先运行了 yarn add --dev moment):

'use strict';

import moment from 'moment';
var rightNow = moment().format('MMMM Do YYYY, h:mm:ss a');
console.log( rightNow );

// "October 23rd 2016, 9:30:24 pm"

我们应该运行:

webpack -p

注意:p 标志表示“生产”模式,这会压缩输出文件。

它会输出一个 dist/app.bundle.js,并将当前日期和时间打印到控制台。要注意 Webpack 会自动识别 上面的 'moment' 指代的是什么(比如说,虽然如果你有一个 moment.js 文件在你的目录,默认情况下 Webpack 会优先考虑你的 moment Node 模块)。

使用多个文件

你可以通过仅仅修改 entry 对象来指定任意数量的 入口 entry / 输出点 output

打包多个文件

'use strict';

const webpack = require("webpack");

module.exports = {
  context: __dirname + "/src",
  entry: {
    app: ["./home.js", "./events.js", "./vendor.js"],
  },
  output: {
    path: __dirname + "/dist",
    filename: "[name].bundle.js",
  },
};

所有文件都会按照数组的顺序一起被打包成一个 dist/app.bundle.js 文件。

输出多个文件

const webpack = require("webpack");

module.exports = {
  context: __dirname + "/src",
  entry: {
    home: "./home.js",
    events: "./events.js",
    contact: "./contact.js",
  },
  output: {
    path: __dirname + "/dist",
    filename: "[name].bundle.js",
  },
};

或者,你可以选择打包成多个 JS 文件以便于分割应用的某些模块。这将被打包成 3 个文件:dist/home.bundle.jsdist/events.bundle.jsdist/contact.bundle.js

高级打包自动化

如果你将你的应用分割成多个 output 输出项(如果你的应用的一部分有大量你不需要预加载的 JS,这会很有用),你可能会重用这些文件的代码,因为它将分别解析每个依赖关系。幸运的是,Webpack 有一个内置的 CommonsChunk 插件来处理这个:

module.exports = {
  // …

  plugins: [
    new webpack.optimize.CommonsChunkPlugin({
      name: "commons",
      filename: "commons.bundle.js",
      minChunks: 2,
    }),
  ],

  // …
};

现在,在你的 output 文件中,如果你有任何模块被加载 2 次以上(通过 minChunks 设置),它会把那个模块打包到 common.js 文件中,然后你可以将其缓存在客户端。这将生成一个额外的请求头,但是你防止了客户端多次下载同一个库。因此,在很多情景下,这会大大提升速度。

开发

Webpack 实际上有自己的开发服务器,所以无论你是开发一个静态网站还是只是你的网站前端原型,它都是无可挑剔的。要运行那个服务器,只需要添加一个 devServer 对象到 webpack.config.js

module.exports = {
  context: __dirname + "/src",
  entry: {
    app: "./app.js",
  },
  output: {
    filename: "[name].bundle.js",
    path: __dirname + "/dist/assets",
    publicPath: "/assets",            // New
  },
  devServer: {
    contentBase: __dirname + "/src",  // New
  },
};

现在创建一个包含以下代码的 src/index.html 文件:

<script src="/assets/app.bundle.js"></script>

……在你的终端中运行:

webpack-dev-server

你的服务器现在运行在 localhost:8080。注意 script 标签里面的 /assets 是怎么匹配到 output.publicPath 的 —— 你可以随意更改它的名称(如果你需要一个 CDN 的时候这会很有用)。

Webpack 会热加载所有 JavaScript 更改,而不需要刷新你的浏览器。但是,所有 webpack.config.js 文件里面的更改都需要重新启动服务器才能生效。

全局访问方法

需要在全局空间使用你的函数?在 webpack.config.js 里面简单地设置 output.library

module.exports = {
  output: {
    library: 'myClassName',
  }
};

……这会将你打包好的文件附加到一个 window.myClassName 实例。因此,使用该命名空间,你可以调用入口文件的可用方法(可以在该文档中阅读有关此设置的更多信息)。

加载器

到目前为止,我们所做的一切只涉及 JavaScript。从一开始就使用 JavaScript 是重要的,因为它是 Webpack 唯一支持的语言。事实上我们可以处理几乎所有文件类型,只要我们将其转换成 JavaScript。我们用 加载器 loader 来实现这个功能。

加载器可以是 Sass 这样的预处理器,或者是 Babel 这样的转译器。在 NPM 上,它们通常被命名为 *-loader,例如 sass-loaderbabel-loader

Babel 和 ES6

如果我们想在项目中通过 Babel 来使用 ES6,我们首先需要在本地安装合适的加载器:

yarn add --dev babel-loader babel-core babel-preset-es2015

然后将它添加到 webpack.config.js,让 Webpack 知道在哪里使用它。

module.exports = {
  // …

  module: {
    rules: [
      {
        test: /\.js$/,
        use: [{
          loader: "babel-loader",
          options: { presets: ["es2015"] }
        }],
      },

      // Loaders for other file types can go here
    ],
  },

  // …
};

Webpack 1 的用户注意:加载器的核心概念没有任何改变,但是语法改进了。直到官方文档完成之前,这可能不是确切的首选语法。

/\.js$/ 这个正则表达式查找所有以 .js 结尾的待通过 Babel 加载的文件。Webpack 依靠正则检查给予你完全的控制权 —— 它不限制你的文件扩展名或者假定你的代码必须以某种方式组织。例如:也许你的 /my_legacy_code/ 文件夹下的内容不是用 ES6 写的,所以你可以修改上述的 test/^((?!my_legacy_folder).)\.js$/,这将会排除那个特定的文件夹,不过会用 Babel 处理其余的文件。

CSS 和 Style 加载器

如果我们只想为我们的应用所需加载 CSS,我们也可以这样做。假设我们有一个 index.js 文件,我们将从那里引入:

import styles from './assets/stylesheets/application.css';

我们会得到以下错误:你可能需要一个合适的加载器来处理这种类型的文件。记住,Webpack 只能识别 JavaScript,所以我们必须安装合适的加载器:

yarn add --dev css-loader style-loader

然后添加一条规则到 webpack.config.js

module.exports = {
  // …

  module: {
    rules: [
      {
        test: /\.css$/,
        use: ["style-loader", "css-loader"],
      },

      // …
    ],
  },
};

加载器以数组的逆序处理。这意味着 css-loader 会比 style-loader 先执行。

你可能会注意到,即使在生产版本中,这实际上是将你的 CSS 和 JavaScript 打包在一起,style-loader 手动将你的样式写到 <head>。乍一看,它可能看起来有点怪异,但你仔细想想就会发现这就慢慢开始变得更加有意义了。你已经节省了一个头部请求 —— 节省了一些连接上的时间。如果你用 JavaScript 来加载你的 DOM,无论如何,这从本质上消除了 FOUC

你还会注意到一个开箱即用的特性 —— Webpack 已经通过将这些文件打包在一起以自动解决你所有的 @import 查询(而不是依靠 CSS 默认的 import 方式,这会导致无谓的头部请求以及资源加载缓慢)。

从你的 JS 加载 CSS 是非常惊人的,因为你现在可以用一种新的强大的方式将你的 CSS 模块化。比如说你要只通过 button.js 来加载 button.css,这将意味着如果 button.js 从来没有真正使用过的话,它的 CSS 就不会膨胀我们的生产版本。如果你坚持面向组件的 CSS 实践,如 SMACSS 或 BEM,你会看到更紧密地结合你的 CSS 和你的标记和 JavaScript 的价值。

CSS 和 Node 模块

我们可以使用 Webpack 来利用 Node.js 使用 ~ 前缀导入 Node 模块的优势。如果我们运行 yarn add normalize.css,我们可以使用:

@import "~normalize.css";

……并且充分利用 NPM 来管理我们的第三方样式 —— 版本控制、没有任何副本和粘贴的部分。此外,让 Webpack 为我们打包 CSS 比起使用 CSS 的默认导入方式有明显的优势 —— 节省无谓的头部请求和加载时间。

更新:这一节和下面一节已经更新为准确的用法,不再使用 CSS 模块简单地导入 Node 的模块。感谢 Albert Fernández 的帮助!

CSS 模块

你可能听说过 CSS 模块,它把 CSS 变成了 SS,消除了 CSS 的 层叠性 Cascading 。通常它的最适用场景是只有当你使用 JavaScript 构建 DOM 的时候,但实质上,它神奇地将你的 CSS 类放置到加载它的 JavaScript 文件里(在这里了解更多)。如果你打算使用它,CSS 模块已经与 css-loader 封装在一起(yarn add --dev css-loader):

module.exports = {
  // …

  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          "style-loader",
          { loader: "css-loader", options: { modules: true } }
        ],
      },

      // …
    ],
  },
};

注意:对于 css-loader,我们现在使用 扩展对象语法 expanded object syntax 来给它传递一个选项。你可以使用一个更为精简的字符串来取代默认选项,正如我们仍然使用了 style-loader


值得注意的是,当允许导入 CSS 模块的时候(例如:@import 'normalize.css';),你完全可以删除掉 ~。但是,当你 @import 你自己的 CSS 的时候,你可能会遇到构建错误。如果你遇到“无法找到 \_\_\_\_”的错误,尝试添加一个 resolve 对象到 webpack.config.js,让 Webpack 更好地理解你的模块加载顺序。

const path = require("path");

module.exports = {
  //…

  resolve: {
    modules: [path.resolve(__dirname, "src"), "node_modules"]
  },
};

我们首先指定源目录,然后指定 node_modules。这样,Webpack 会更好地处理解析,按照既定的顺序(分别用你的源目录和 Node 模块的目录替换 "src""node_modules"),首先查找我们的源目录,然后再查找已安装的 Node 模块。

Sass

需要使用 Sass?没问题。安装:

yarn add --dev sass-loader node-sass

并添加新的规则:

module.exports = {
  // …

  module: {
    rules: [
      {
        test: /\.(sass|scss)$/,
        use: [
          "style-loader",
          "css-loader",
          "sass-loader",
        ]
      }

      // …
    ],
  },
};

然后当你的 Javascript 对一个 .scss.sass 文件调用 import 方法的时候,Webpack 会处理的。

CSS 独立打包

或许你在处理渐进增强的问题;或许你因为其它原因需要一个单独的 CSS 文件。我们可以通过在我们的配置中用 extract-text-webpack-plugin 替换 style-loader 而轻易地做到这一点,这不需要更改任何代码。以我们的 app.js 文件为例:

import styles from './assets/stylesheets/application.css';

让我们安装这个插件到本地(我们需要 2016 年 10 月的测试版本):

yarn add --dev [email protected]

并且添加到 webpack.config.js

const ExtractTextPlugin = require("extract-text-webpack-plugin");

module.exports = {
  // …

  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          ExtractTextPlugin.extract("css"),
          { loader: "css-loader", options: { modules: true } },
        ],
      },

      // …
    ]
  },
  plugins: [
    new ExtractTextPlugin({
      filename: "[name].bundle.css",
      allChunks: true,
    }),
  ],
};

现在当运行 webpack -p 的时候,你的 output 目录还会有一个 app.bundle.css 文件。只需要像往常一样简单地在你的 HTML 中向该文件添加一个 <link> 标签即可。

HTML

正如你可能已经猜到,Webpack 还有一个 [html-loader][6] 插件。但是,当我们用 JavaScript 加载 HTML 时,我们针对不同的场景分成了不同的方法,我无法想出一个单一的例子来为你计划下一步做什么。通常,你需要加载 HTML 以便于在更大的系统(如 ReactAngularVueEmber)中使用 JavaScript 风格的标记,如 JSXMustacheHandlebars。或者你可以使用类似 Pug (以前叫 Jade)或 Haml 这样的 HTML 预处理器,抑或你可以直接把同样的 HTML 从你的源代码目录推送到你的构建目录。你怎么做都行。

教程到此为止了:你可以用 Webpack 加载标记,但是进展到这一步的时候,关于你的架构,你将做出自己的决定,我和 Webpack 都无法左右你。不过参考以上的例子以及搜索 NPM 上适用的加载器应该足够你发展下去了。

从模块的角度思考

为了充分使用 Webpack,你必须从模块的角度来思考:细粒度的、可复用的、用于高效处理每一件事的独立的处理程序。这意味着采取这样的方式:

└── js/
    └── application.js   // 300KB of spaghetti code

将其转变成这样:

└── js/
    ├── components/
    │   ├── button.js
    │   ├── calendar.js
    │   ├── comment.js
    │   ├── modal.js
    │   ├── tab.js
    │   ├── timer.js
    │   ├── video.js
    │   └── wysiwyg.js
    │
    └── application.js  // ~ 1KB of code; imports from ./components/

结果呈现了整洁的、可复用的代码。每一个独立的组件通过 import 来引入自身的依赖,并 export 它想要暴露给其它模块的部分。结合 Babel 和 ES6,你可以利用 JavaScript 类 来实现更强大的模块化,而不用考虑它的工作原理。

有关模块的更多信息,请参阅 Preethi Kasreddy 这篇优秀的文章


延伸阅读


via: https://blog.madewithenvy.com/getting-started-with-webpack-2-ed2b86c68783#.oozfpppao

作者:Drew Powers 译者:OneNewLife 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

前一段时间,我们已经分享了如何在诸如 Debian、Ubuntu、Linux Mint、Elementary OS 的基于 DEB 的系统中强制用户使用高强度的密码 ,比如。那么,你可能会疑惑一个高强度的密码究竟是什么样的呢?怎么才能生成一个那样的密码呢?不用担心,下面我们将介绍 4 种简单方法让你在 Linux 中生成一个高强度密码。当然,已经有很多免费的工具或者方式来完成这个任务,但这里我们仅考虑那些简单直接的方法。下面就让我们开始吧。

1. 在 Linux 中使用 OpenSSL 来生成一个高强度密码

OpenSSL 在所有的类 Unix 发行版、Solaris、Mac OS X 和 Windows 中都可以获取到。

要使用 OpenSSL 生成一个随机密码,打开终端并运行下面的命令:

openssl rand 14 -base64

上面的 -base64 参数将确保生成的密码可以被键盘敲出来。

输出样例:

wXCHXlxuhrFrFMQLqik=

上面的命令将生成一个随机的、长度为 14 个字符的高强度密码。我们强烈推荐你生成 14 个字符的密码。 当然你可以使用 OpenSSL 生成任意长度的密码。

要了解更多信息,可以参考联机手册:

man openssl

2. 在 Linux 中使用 Pwgen 来生成一个高强度密码

pwgen 是一个简单却非常有用的命令行工具,用它可以在短时间内生成一个随机且高强度的密码。它设计出的安全密码可以被人们更容易地记住。在大多数的类 Unix 系统中都可以获取到它。

在基于 DEB 的系统中安装 pwgen 请运行:

sudo apt-get install pwgen

在基于 RPM 的系统中,运行:

sudo yum install pwgen

在基于 Arch 的系统中,则运行:

sudo pacman -S pwgen

pwgen 安装完成后,便可以使用下面的命令来生成一个长度为 14 个字符的随机高强度密码:

pwgen 14 1

输出样例:

Choo4aicozai3a

上面的命令将生成一个 14 位字符长的密码,如果要生成两个不同的 14 位字符长的密码,则可以运行:

pwgen 14 2

输出样例:

xee7seerez6Kau Aeshu0geveeji8

如果要生成 100 个(尽管可能没有必要生成那么多)不同的 14 位字符长的密码,则可以运行:

pwgen 14

输出样例:

kaeNg3EiVei4ei Oo0iehiJaix5Ae aenuv2eree2Quo iaT7zahH1eN2Aj Bie2owaiFahsie
gaan9zu5Xeh5ah ahGeeth8ea5ooh Ir0ueda5poogh5 uo0ohqu2ufaiX2 Mei0pee6Og3zae
Oofeiceer8Aipu sheew3aeReidir Dee4Heib2eim2o eig6jar8giPhae Zahde9nae1Niew
quatol5Oi3Bah2 quue4eebaiNgaa oGoahieSh5oL4m aequeeQue2piti laige5seePhugo
iiGo9Uthee4ros WievaiQu2xech6 shaeve0maaK3ae ool8Pai2eighis EPheiRiet1ohci
ZieX9outhoht8N Uh1UoPhah2Thee reaGhohZae5idi oiG4ooshiyi5in keePh1ohshei8y
aim5Eevah2thah Xaej8tha5eisho IeGie1Anaalaev gaoY3ohthooh3x chaebeesahTh8e
soh7oosieY5eiD ahmoh6Ihii6que Shoowoo5dahbah ieW0aiChubee7I Caet6aikai6aex
coo1du2Re9aika Ohnei5Egoh7leV aiyie6Ahdeipho EiV0aeToeth1da iNgaesu4eeyu0S
Eeb1suoV3naera railai2Vaina8u xu3OhVee1reeyu Og0eavae3oohoh audahneihaeK8a
foo6iechi5Eira oXeixoh6EwuboD we1eiDahNgoh9s ko1Eeju1iedu1z aeP7achiisohr7
phang5caeGei5j ait4Shuo5Aitai no4eis9Tohd8oh Quiet6oTaaQuei Dei2pu2NaefeCa
Shiim9quiuy0ku yiewooph3thieL thu8Aphai1ieDa Phahnahch1Aam1 oocex7Yaith8oo
eraiGaech5ahNg neixa3malif5Ya Eux7chah8ahXix eex1lahXae4Mei uGhahzonu6airu
yah8uWahn3jeiW Yi4ye4Choongie io1Vo3aiQuahpi rie4Rucheet6ae Dohbieyaeleis5
xi1Zaushohbei7 jeeb9EiSiech0u eewo0Oow7ielie aiquooZamah5th kouj7Jaivohx9o
biyeeshesaDi9e she9ooj3zuw6Ah Eit7dei1Yei5la xohN0aeSheipaa Eeg9Phob6neema
eengoneo4saeL4 aeghi4feephu6W eiWash2Vie1mee chieceish5ioPe ool4Hongo7ef1o
jahBe1pui9thou eeV2choohoa4ee Ohmae0eef4ic8I Eet0deiyohdiew Ke9ue5thohzei3
aiyoxeiva8Maih gieRahgh8anahM ve2ath9Eyi5iet quohg6ok3Ahgee theingaech5Nef

如果要在密码中包含至少 1 个数字,则可以运行:

pwgen 14 1 -n 1

输出样例:

xoiFush3ceiPhe

另外,pwgen 命令还有一些很实用的选项:

  • -c--capitalize 在密码中包含至少一个大写字母
  • -A--no-capitalize 在密码中不包含大写字母
  • -n--numerals 在密码中包含至少一个数字
  • -0--no-numerals 在密码中不包含数字
  • -y--symbols 在密码中包含至少一个特殊字符
  • -s--secure 生成完全随机的密码
  • -B--ambiguous 在密码中不包含难于区分的字母,如 0o1l
  • -h--help 输出帮助信息
  • -H--sha1=path/to/file[#seed] 使用某个给定文件的 sha1 哈希值来作为随机数的生成种子
  • -C 按列输出生成好的密码
  • -1 不按列输出生成好的密码
  • -v--no-vowels 不使用任何元音字母,以防止生成下流的词语 `

若想了解更多信息,请查阅其联机手册:

man pwgen

3. 在 Linux 中使用 GPG 来生成一个高强度密码

GPG (GnuPG 或 GNU Privacy Guard) 是一个自由开源的命令行程序,可以用于替代赛门铁克的 PGP 加密软件。在类 Unix 操作系统、Microsoft Windows 和 Android 中都可以获取到它。

要使用 PGP 生成 1 个长度为 14 个字符的高强度密码,请在终端中运行下面的命令:

 gpg --gen-random --armor 1 14

输出样例:

DkmsrUy3klzzbIbavx8=

上面的命令将生成一个安全、随机、高强度且基于 base64 编码的密码。

4. 在 Linux 中使用 Perl 来生成一个高强度密码

Perl 在大多数 Linux 发行版本的默认软件仓库中都可以获取到,你可以使用相应的包管理器来安装它。

例如在基于 DEB 的系统中,可以运行下面的命令来安装 Perl:

sudo apt-get install perl

在基于 RPM 的系统中安装 Perl,可以运行:

sudo yum install perl

在基于 Arch 的系统中,则运行:

sudo pacman -S perl

一旦 Perl 安装完成,使用下面的命令创建一个文件:

vi password.pl

接着添加下面的内容到这个文件中:

#!/usr/bin/perl

my @alphanumeric = ('a'..'z', 'A'..'Z', 0..9);
my $randpassword = join '', map $alphanumeric[rand @alphanumeric], 0..8;
print "$randpassword\n"

保存并关闭该文件。

接着,切换到你刚才保存文件的地方,并运行下面的命令:

perl password.pl

使用你自己定义的文件名来替换上面命令中的 password.pl

输出样例:

3V4CJJnYd

注: 我无法找到这个脚本的原作者,假如你知道作者的名字,请在下面的评论部分让我知晓,我将在这篇指南中添加上该作者的名字。

请注意:对于生成的密码,你必须记住它,或者将它保存到电脑中一个安全的地方。我建议你记住密码并将它从系统中删除,因为这比你的系统被黑客控制要好的多。

伙计们,今天就是这么多了。不久我将带来另一篇有意思的文章。在此之前,敬请继续关注。


via: https://www.ostechnix.com/4-easy-ways-to-generate-a-strong-password-in-linux/

作者: SK 译者:FSSlc 校对:jasminepeng

本文由 LCTT 原创编译,Linux中国 荣誉推出