首页 文章 精选 留言 我的

精选列表

搜索[博客搭建],共10000篇文章
优秀的个人博客,低调大师

Ubuntu 安装php环境 lamp 搭建网站

1.Apache安装 首先安装apache服务器,ubuntu下面使用apt-get来下载安装软件。 sudo apt-get install apache2 输入密码后,便开始下载安装了,安装好后打开浏览器,输入localhost查看是否安装成功 如果如上显示的话,说明安装成功了。 2.PHP安装 这里我准备安装PHP7.0版本的,在命令行输入: sudo apt-get install php7.0 安装完成后输入:php -v查看PHP是否安装成功 php -v PHP和Apache都安装好后就需要让Apache能够识别解析PHP文件,我们先搜一下有没有适合PHP7的插件,输入命令: apt-cache search libapache2-mod-php 可以看到搜出来的结果里面有一个是PHP7.0版本的,我们就安装这个: sudo apt-get install libapache2-mod-php7.0 下面我们就可以随便写一个php文件看是否可以解析访问。输入命令: cd /var/www/html 切换到apache项目目录下,新建文件: sudo vim test.php 内容: <?php phpinfo(); ?> 保存后浏览器访问:localhost/test.php 如果一切正常的话,就会看到php的一些信息。 3.Mysql安装 接下来就是安装数据库Mysql了,数据库需要装服务端和客户端两个,输入命令: sudo apt-get install mysql-server mysql-client 安装过程中会提示设置root账号的登录密码,输入后选择OK继续安装 安装完成后,输入mysql -V查看安装的版本信息 mysql -V 同样的,我们还需要让mysql能够和php互动,安装php的mysql插件: sudo apt-get install php7.0-mysql 最后我们还可以安装一些常用的php扩展 sudo apt-get install php7.0-gd php7.0-mbstring php7.0-xml 到此关于lamp的软件就安装完成了,最后还可以安装一下composer: sudo apt-get install composer 安装好后输入命令:composer查看是否成功 composer 如图显示,安装过程就全部完成了。 php 环境相关问题: 准备通过phpinfo()获取php的所有配置文件路径test.php 内容 <?php phpinfo(); ?> 1.curl 未开启,请先开启mbstring扩展 解决方法: 安装插件 sudo apt-get install curl libcurl4 libcurl3-dev php7.2-curl 开启权限 sudo sudo vim /etc/php/7.2/apache2/php.ini php.ini当中的 ;extension=php_curl.dll (去掉注释) 改成 extension=php_curl.dll 重启服务 sudo /etc/init.d/apache2 restart 2.mbstring 未开启,请先开启mbstring扩展 解决方法: 安装插件 sudo apt-get install php7.2-mbstring 开启权限 sudo sudo vim /etc/php/7.2/apache2/php.ini ;extension=php_mbstring.dll 改为 extension=php_mbstring.dll 去掉分号的注释作用 重启服务 sudo /etc/init.d/apache2 restart 3.cache 无效,请先设置目录读写权限,请联系您的空间或者服务器提供商 Linux php根目录下: cd /var/www/html/ mkdir cache chmod 777 cache chmod 777 index.php

优秀的个人博客,低调大师

Centos7 搭建LDAP并启用TLS加密

简介 LDAP(轻量级目录访问协议,Lightweight Directory Access Protocol)是为了实现目录服务的信息服务。 目录服务是一种特殊的数据库系统,其专门针对读取,浏览和搜索操作进行了特定的优化。在网络中应用了LDAP后,用户只需要使用一个账号和密码就可以轻松访问网络中的所有服务,实现用户身份的统一认证。 简单来说:拿LDAP来统一管理一些账号,例如: Gitlab,JenKins,Samba,SVN,Zabbix等。 关于SSL/TLS LDAP over SSL # LDAP over SSL 也就是 ldaps # ldap默认不加密情况下是走的389端口 # 当使用ldaps的时候走的就是636端口了 # 可以简单理解成http和https的关系 # 当然ldaps已经淘汰了,不然也不会有LDAP over TLS出来 LDAP over TLS # TLS可以简单理解为ldaps的升级 # 它默认走389端口,但是会通讯的时候加密 # 客户端连接LDAP时,需要指明通讯类型为TLS,所以他可以跟不加密的模式一样,任意端口都行 对比一下连接方式: ldaps: ldapsearch -H ldaps://127.0.0.1 TLS: ldapsearch -ZZ -H ldap://127.0.0.1 环境 CentOS Linux release 7.5.1804 Kernel 4.20.0-1.el7.elrepo.x86_64 docker-ce 18.09 docker-compose 1.23.1 安装docker-compose yum install -y python-pip pip install docker-compose docker-compose -v 准备证书 安装cfssl wget -O /bin/cfssl https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 wget -O /bin/cfssljson https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 wget -O /bin/cfssl-certinfo https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 for cfssl in `ls /bin/cfssl*`;do chmod +x $cfssl;done; 配置证书信息 cd $HOME && mkdir ssl && cd ssl # ca配置文件 cat > ca-config.json << EOF { "signing": { "default": { "expiry": "87600h" }, "profiles": { "ldap": { "usages": [ "signing", "key encipherment", "server auth", "client auth" ], "expiry": "87600h" } } } } EOF # 自签名ca的证书申请 cat > ldap-ca-csr.json << EOF { "CN": "ldap", "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "Shenzhen", "L": "Shenzhen", "O": "ldap", "OU": "LDAP Security" } ] } EOF # ldap证书申请资料 # 下面hosts字段里就是使用这张证书的主机 # 特别注意一定要加上宿主机的IP地址,反正是自己颁发的证书,怎么加都行!!! # 加上本机回环地址,加上ldap容器名,我这里容器名待会设置成openldap # 如果你要放到公网去的话,那一可以加上FQDN地址 cat > ldap-csr.json << EOF { "CN": "ldap", "hosts": [ "127.0.0.1", "192.168.1.1", "openldap", "ldap.lotbrick.com", "lotbrick.com" ], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "Shenzhen", "L": "Shenzhen", "O": "ldap", "OU": "LDAP Security" } ] } EOF 给证书签名 # CA自签名 cfssl gencert -initca ldap-ca-csr.json | cfssljson -bare ca # LDAP证书签名,ldap需要的文件为:ca证书,ldap证书,ldap私钥 cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=ldap ldap-csr.json | cfssljson -bare ldap # 查看生成的证书 # 其中 ldap-key.pem ldap.pem ca.pem 是我们需要的 [root@master ssl]#ls ca-config.json ca.csr ca-key.pem ca.pem ldap-ca-csr.json ldap.csr ldap-csr.json ldap-key.pem ldap.pem 开始安装ldap 克隆仓库,获取docker-compose.yaml文件 cd $HOME git clone https://github.com/JyBigBoss/docker-compose.git cd docker-compose/LDAP/ 复制证书 mkdir ssl/ cp $HOME/ssl/{ldap-key.pem,ldap.pem,ca.pem} ssl/ 修改docker-compose.yaml文件 vi docker-compose.yaml # 修改下面的几项 # 镜像使用的是osixia/openldap # 详细的配置解释:https://github.com/osixia/docker-openldap LDAP_ORGANISATION: "lotbrick.com" LDAP_DOMAIN: "lotbrick.com" LDAP_ADMIN_PASSWORD: "admin" LDAP_CONFIG_PASSWORD: "admin" LDAP_TLS: "true" LDAP_TLS_CRT_FILENAME: "ldap.pem" LDAP_TLS_KEY_FILENAME: "ldap-key.pem" LDAP_TLS_CA_CRT_FILENAME: "ca.pem" LDAP_TLS_ENFORCE: "true" LDAP_TLS_VERIFY_CLIENT: "try" domainname: "lotbrick.com" hostname: "lotbrick.com" # 特别注意LDAP_TLS_VERIFY_CLIENT # 不要设置成demand,这个选项可以理解成双向认证,也就是客户端连接ldap时也许要提供证书,也就是客户端也需要有自己的证书 # 设置成try就行,客户端不提供证书也能连接,反正连接已经加密了。 # 官方文档:http://www.openldap.org/doc/admin24/tls.html 启动ldap #第一次启动会比较慢,淡定点 docker-compose pull docker-compose up -d ls docker ps -a # 启动之后会生成几个文件夹 # ldapconf保存的是ldap的配置文件 # ldapdata保存的是ldap的数据 # lam保存的是lam管理工具的配置 [root@master LDAP]#docker-compose up -d Creating network "ldap_default" with the default driver Creating openldap ... done Creating ldap-account-manager ... done [root@master LDAP]#ls docker-compose.yaml lam ldapconf ldapdata ssl [root@master LDAP]#docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 9b4ebdad17eb jinyunboss/ldap-account-manager:6.6 "docker-php-entrypoi…" 2 minutes ago Up 2 minutes 0.0.0.0:8080->80/tcp ldap-account-manager a7ff3bd5dced osixia/openldap:1.2.2 "/container/tool/run" 2 minutes ago Up 2 minutes 0.0.0.0:389->389/tcp, 0.0.0.0:636->636/tcp openldap 打开浏览器,配置LDAP Account Manager LDAP Account Manager容器监听在8080端口 打开http://192.168.1.1:8080 # 配置一下lam管理页面 # lam管理界面默认密码是: lam # lam可以管理多个ldap服务器,所以可以拥有多个profile,每个profile对应一台服务器 # 简单添加个用户,然后用另一台linux机器测试ldap连接 测试LDAP 安装ldap客户端 yum install -y openldap-clients nss-pam-ldapd 配置配置客户端 # 配置系统使用ldap认证 authconfig-tui # 将自签名的ca证书给客户端 cd /etc/openldap/cacerts/ # 修改/etc/nslcd.conf,添加管理员凭据 echo "binddn cn=admin,dc=lotbrick,dc=com" >> /etc/nslcd.conf echo "bindpw admin" >> /etc/nslcd.conf cat /etc/nslcd.conf # 重启nslcd服务 systemctl restart nslcd 测试 # 执行命令看看能不能读取到LDAP用户 # 能连接上ldap的话,执行之后会出现ldap用户 getent passwd id bigboss # 切换成bigboss用户试试 su - bigboss

优秀的个人博客,低调大师

Android 仿IOS的PopupWindow和通用BasePopupWindow搭建

截图 pw.png 实现 1、BasePopupWindow.java 1.1、实现动态加载不同layout 1.2、动态配置是否弹出后背景半透明,关闭时候恢复(监听ondismiss,靠window类来变色) 1.3、一些基础性的方法抽象方法 1.4、为了更加复杂的样式和动效,可以继续扩展此类 /** * Created by wujn on 2018/10/29. * Version : v1.0 * Function: base popuwindow */ public abstract class BasePopupWindow extends PopupWindow implements View.OnClickListener{ /** * 上下文 */ private Context context; /** * 最上边的背景视图 */ private View vBgBasePicker; /** * 内容viewgroup */ private LinearLayout llBaseContentPicker; public BasePopupWindow(Context context) { super(context); this.context = context; View parentView = View.inflate(context, R.layout.base_popup_window_picker, null); vBgBasePicker = parentView.findViewById(R.id.v_bg_base_picker); llBaseContentPicker = (LinearLayout) parentView.findViewById(R.id.ll_base_content_picker); /*** * 添加布局到界面中 */ llBaseContentPicker.addView(View.inflate(context, bindLayout(), null)); setContentView(parentView); //设置PopupWindow弹出窗体的宽 this.setWidth(ViewGroup.LayoutParams.MATCH_PARENT); //设置PopupWindow弹出窗体的高 this.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT); //在PopupWindow里面就加上下面代码,让键盘弹出时,不会挡住pop窗口。 this.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED); this.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); setFocusable(true);//设置获取焦点 setTouchable(true);//设置可以触摸 setOutsideTouchable(true);//设置外边可以点击 ColorDrawable dw = new ColorDrawable(0xffffff); setBackgroundDrawable(dw); //设置SelectPicPopupWindow弹出窗体动画效果 this.setAnimationStyle(R.style.BottomDialogWindowAnim); initView(parentView); initListener(); initData(); vBgBasePicker.setOnClickListener(this); //是否需要屏幕半透明 setBackgroundHalfTransition(isNeedBackgroundHalfTransition()); } /** * 初始化布局 * * @return */ protected abstract int bindLayout(); /** * 初始化view * * @param parentView */ protected abstract void initView(View parentView); /** * 初始化数据 */ protected abstract void initData(); /** * 初始化监听 */ protected abstract void initListener(); /** * 为了适配7.0系统以上显示问题(显示在控件的底部) * * @param anchor */ @Override public void showAsDropDown(View anchor) { if (Build.VERSION.SDK_INT >= 24) { Rect rect = new Rect(); anchor.getGlobalVisibleRect(rect); int h = anchor.getResources().getDisplayMetrics().heightPixels - rect.bottom; setHeight(h); } super.showAsDropDown(anchor); if(isNeedBgHalfTrans){ backgroundAlpha(0.5f); } } /** * 展示在屏幕的底部 * * @param layoutid rootview */ public void showAtLocation(@LayoutRes int layoutid) { showAtLocation(LayoutInflater.from(context).inflate(layoutid, null), Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 0); if(isNeedBgHalfTrans){ backgroundAlpha(0.5f); } } /** * 最上边视图的点击事件的监听 * * @param v */ @Override public void onClick(View v) { switch (v.getId()) { case R.id.v_bg_base_picker: dismiss(); break; } } /** * 是否设置背景半透明 * */ public boolean isNeedBackgroundHalfTransition(){ return false; } private boolean isNeedBgHalfTrans = false; private void setBackgroundHalfTransition(boolean isNeed){ isNeedBgHalfTrans = isNeed; if(isNeedBgHalfTrans){ this.setOnDismissListener(new OnDismissListener() { @Override public void onDismiss() { backgroundAlpha(1f); } }); } } /** * 设置添加屏幕的背景透明度 * @param bgAlpha */ private void backgroundAlpha(float bgAlpha) { WindowManager.LayoutParams lp = ((Activity)context).getWindow().getAttributes(); lp.alpha = bgAlpha; //0.0-1.0 ((Activity)context).getWindow().setAttributes(lp); } } 2、base_popup_window_picker.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <View android:id="@+id/v_bg_base_picker" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" /> <LinearLayout android:id="@+id/ll_base_content_picker" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:orientation="vertical" /> </LinearLayout> 3、进入和退出时候的动画style <!--animanation--> <!-- 底部的dialog弹出的动画样式--> <style name="BottomDialogWindowAnim" parent="android:Animation"> <item name="android:windowEnterAnimation">@anim/popup_bottom_enter_anim</item> <item name="android:windowExitAnimation">@anim/popup_bottom_exit_anim</item> </style> 进入动画:popup_bottom_enter_anim.xml <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" > <translate android:duration="200" android:fromYDelta="100%p" android:toYDelta="0" /> <alpha android:duration="200" android:fromAlpha="0.0" android:toAlpha="1.0" /> </set> 退出动画:popup_bottom_exit_anim.xml <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:duration="200" android:fromYDelta="0" android:toYDelta="50%p" /> <alpha android:duration="200" android:fromAlpha="1.0" android:toAlpha="0.0" /> </set> 4、仿IOS的layout:popup_window_album_or_camera.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="10dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/bg_shape_corner_white" android:orientation="vertical"> <Button android:id="@+id/btnCamera" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@null" android:text="拍照" android:textColor="@color/dodgerblue" android:textSize="@dimen/normal_text_size" /> <View android:layout_width="match_parent" android:layout_height="1dp" android:background="@color/gray_1" /> <Button android:id="@+id/btnAlbum" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@null" android:text="从相册中选择" android:textColor="@color/dodgerblue" android:textSize="@dimen/normal_text_size" /> </LinearLayout> <LinearLayout android:layout_marginTop="10dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/bg_shape_corner_white" android:orientation="vertical"> <Button android:id="@+id/btnCancel" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@null" android:text="@string/cancel" android:textColor="@color/dodgerblue" android:textSize="@dimen/normal_text_size" /> </LinearLayout> </LinearLayout> item的背景style <?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="@color/white" /> <corners android:radius="6dp"/> <stroke android:width="1dp" android:color="@color/gray_1" /> </shape> 5、仿IOS的popuwindow类:AlbumOrCameraPopupWindow public class AlbumOrCameraPopupWindow extends BasePopupWindow { private Button btnCamera; private Button btnAlbum; private Button btnCancel; private OnCameraOrAlbumSelectListener onCameraOrAlbumSelectListener; public AlbumOrCameraPopupWindow(Context context,OnCameraOrAlbumSelectListener onCameraOrAlbumSelectListener) { super(context); this.onCameraOrAlbumSelectListener = onCameraOrAlbumSelectListener; } @Override public boolean isNeedBackgroundHalfTransition(){ return true; } @Override protected int bindLayout() { return R.layout.popup_window_album_or_camera; } @Override protected void initView(View parentView) { btnCamera = (Button) parentView.findViewById(R.id.btnCamera); btnAlbum = (Button) parentView.findViewById(R.id.btnAlbum); btnCancel = (Button) parentView.findViewById(R.id.btnCancel); } @Override protected void initData() { } @Override protected void initListener() { btnCamera.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dismiss(); if(onCameraOrAlbumSelectListener != null){ onCameraOrAlbumSelectListener.OnSelectCamera(); } } }); btnAlbum.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dismiss(); if(onCameraOrAlbumSelectListener != null){ onCameraOrAlbumSelectListener.OnSelectAlbum(); } } }); btnCancel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { dismiss(); } }); } } 选择相机或者相册的监听接口 public interface OnCameraOrAlbumSelectListener { public void OnSelectCamera(); public void OnSelectAlbum(); } 6、具体使用 private AlbumOrCameraPopupWindow ACWindow; private void initListener(){ ACWindow = new AlbumOrCameraPopupWindow(this, onCameraOrAlbumSelectListener); btnIosPopupWindow.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(ACWindow != null && !ACWindow.isShowing()){ ACWindow.showAtLocation(R.layout.activity_view_popup_window); } } }); } /**选择相机或者相册*/ private OnCameraOrAlbumSelectListener onCameraOrAlbumSelectListener = new OnCameraOrAlbumSelectListener() { @Override public void OnSelectCamera() { LogUtil.i("OnSelectCamera..."); ToastUtil.showShort(instance, "相机"); } @Override public void OnSelectAlbum() { LogUtil.i("OnSelectAlbum..."); ToastUtil.showShort(instance, "从相册中选择"); } }; 朝CV工程师又进一步~~~

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册