windows下使用PHP实现定时执行脚本

mikel阅读(927)

一直以来,使用PHP定时运行脚本都是让大家头痛的问题,但是我们确实可以利用windows的计划任务来定时调用PHP脚本,当然这还要感谢PHP.exe。下面,站长将向大家介绍,如何来实现。

目标:根据系统时间定时执行PHP脚本,不需要人工运行(这里以定时新建一个文本文件并写入内容为例)

解决步骤:

1、建立PHP脚本,如下:
<meta charset=’utf-8′>
<?php
file_put_contents(‘D:\www\root\1.txt’,’ok’);
?>
大家,可以看见,我们在这里对将要创建的文件路径使用了绝对路径,这是因为我们将要通过windows命令行来调用此脚本,由于cmd.exe与我们的web根目录是不一样的,而php的文件目录函数只能在web根目录范围内进行操作,所以我们需要使用绝对路径,否则代码将正确执行但是文件将不会被创建。
2、新建.bat文件,代码如下:

“D:\Program Files\wamp\bin\php\php5.3.10\php.exe” -f “D:\www\test\index.php”
保存,并命名为run.bat。

注意,如果你的PHP目录或web根目录中含有空格,你需要使用引号将整个路径引用起来,否则将运行错误。站长的目录中含有空格,因此使用了引号。创建属于你自己的bat文件时,请根据自身情况决定是否要使用引号和文件的目录。

3、添加windows计划任务
从控制面板中打开计划任务(这里主要针对win7用户进行说明),点击“创建基本任务”,填写名称和描述,然后点击“下一步”,选择任务执行的频率,很好理解,然后点击“下一步”,设置任务的执行时间,然后点击“下一步”,选择“启动程序”,点击“下一步”,点击浏览按钮选择我们建立的“run.bat”文件,点击”下一步“,点击”完成“。

4、运行
根据你设置的时间,系统会定时自动运行,如果你等不及也可以手动执行。在”计划任务“中间栏下方的任务名中查找你刚才新建的任务,鼠标双击该任务,单击右边的运行按钮,系统会弹出一个cmd对话框然后关闭,这说明你的脚本已经正确执行了,到创建文件的目录去检查文件是否创建。

微擎路由、site.php - GZX的专栏 - 博客频道 - CSDN.NET

mikel阅读(891)

来源: 微擎路由、site.php – GZX的专栏 – 博客频道 – CSDN.NET

URL路由
解析路由
约定及使用
创建一个URL
URL路由

入口脚本程序获取到到URL中相关的GET参数,解析后进行权限判断,然后调用相应的控制器处理这个请求。该过程就被称为URL路由(routing)。

解析路由

地址URL地址路由

当传入的URL请求中包含一个名为 c、a、do(可选) 的 GET 参数,它即被视为一个路由,例如:

http://we7.cc/web/index.php?c=platform&a=menu&
则会路由至 /web/source/platform/menu.ctrl.PHP 文件中

http://we7.cc/app/index.php?c=mc&a=home&
则会路由至 /app/source/mc/home.ctrl.php 文件中

模块URL地址路由

当传入的 c 值为 “site”, a 值为 “entry”时则是一个模块路由,例如:

http://we7.cc/web/index.php?c=site&a=entry&do=themeset&m=we7_demo
则会路由至 /addons/we7_demo/site.php 文件中的 doWebThemeset() 方法。

http://we7.cc/app/index.php?i=1&j=2&c=entry&do=list&m=we7_demo
则会路由至 /addons/we7_demo/site.php 文件中的 doMobileList() 方法。

约定及使用

GET 参数中的 c、a、do为微擎系统的路由参数,应当避免与系统参数冲突,在程序中可以使用 controlleraction、$do来获取对应的路由三个参数

创建一个URL

微擎提供一个创建URL的函数 url(segment,params = array(), $noredirect = false) , 路由的表达式以斜杠“/”的方式组织,每个以斜杠分隔的片段都是指向某一控制器(controller)、操作(action)或是行为(do)。
第二个参数则是以数组的形式表示URL中的QueryString。例如:

//生成此地址
//http://we7.cc/web/index.php?c=site&a=entry&do=themeset&m=we7_demo
echo url(‘site/entry/themeset’, array(‘m’ => ‘we7_demo’));

//http://we7.cc/app/index.php?c=mc&a=home&
echo url(‘mc/home’);
模块中二次封装了系统的 url() 函数,使用时变的更加简单,例如:

class We7_demoModuleSite extends WeModuleSite {
public function doMobileIndex() {
echo $this->createMobileUrl(‘home’);
}

public function doMobileHome() {
    //上面doMobileIndex()生成的链接会进入到这里
}

publci function doWebIndex() {
    echo $this->createWebUrl('home');
}

public function doWebHome() {
    //上面doWebIndex()生成的链接会进入到这里
}

}

微信公众平台开发(76) 获取用户基本信息 - 方倍工作室 - 博客园

mikel阅读(977)

来源: 微信公众平台开发(76) 获取用户基本信息 – 方倍工作室 – 博客园

本文介绍如何获得微信公众平台关注用户的基本信息,包括昵称、头像、性别、国家、省份、城市、语言。
本文的方法将囊括订阅号和服务号以及自定义菜单各种场景,无论是否有高级接口权限,都有办法来获得用户基本信息,而无需模拟登录。

 

在本文中,特别要注意的是有两个不同的Access Token,他们产生的方式不一样,一种是使用AppID和AppSecret获取的access_token,一种是OAuth2.0授权中产生的access_token,方倍工作室分别称为全局Access Token和授权Access Token。

 

一、通过全局Access Token获取用户基本信息

1. 用户关注以及回复消息的时候,均可以获得用户的OpenID

复制代码
<xml>
    <ToUserName><![CDATA[gh_b629c48b653e]]></ToUserName>
    <FromUserName><![CDATA[ollB4jv7LA3tydjviJp5V9qTU_kA]]></FromUserName>
    <CreateTime>1372307736</CreateTime>
    <MsgType><![CDATA[event]]></MsgType>
    <Event><![CDATA[subscribe]]></Event>
    <EventKey><![CDATA[]]></EventKey>
</xml>
复制代码

其中的FromUserName就是OpenID

2. 然后使用access_token接口,请求获得全局Access Token

https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

返回结果:

{
    "access_token": "NU7Kr6v9L9TQaqm5NE3OTPctTZx797Wxw4Snd2WL2HHBqLCiXlDVOw2l-Se0I-WmOLLniAYLAwzhbYhXNjbLc_KAA092cxkmpj5FpuqNO0IL7bB0Exz5s5qC9Umypy-rz2y441W9qgfnmNtIZWSjSQ",
    "expires_in": 7200
}

3. 再使用全局ACCESS_TOKEN获取OpenID的详细信息

https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID

返回如下:

复制代码
{
    "subscribe": 1,
    "openid": "oLVPpjqs2BhvzwPj5A-vTYAX4GLc",
    "nickname": "刺猬宝宝",
    "sex": 1,
    "language": "zh_CN",
    "city": "深圳",
    "province": "广东",
    "country": "中国",
    "headimgurl": "http://wx.qlogo.cn/mmopen/JcDicrZBlREhnNXZRudod9PmibRkIs5K2f1tUQ7lFjC63pYHaXGxNDgMzjGDEuvzYZbFOqtUXaxSdoZG6iane5ko9H30krIbzGv/0",
    "subscribe_time": 1386160805
}
复制代码

至此,获得用户的基本信息。

这种方式最适合用户在关注的时候,回复一条欢迎关注+用户昵称的信息,如关注下面公众账号时的回复所示。扫描二维码可体验。

 

 

二、通过OAuth2.0方式弹出授权页面获得用户基本信息

1. 首先配置回调域名

2. 构造请求url如下:

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx8888888888888888&redirect_uri=http://mascot.duapp.com/oauth2.php&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect

页面URL中的

scope=snsapi_userinfo 表示应用授权作用域为请求用户信息
★ 如果使用别人的AppID和AppSecret,那么获得的OpenID是那个有高级接口权限的服务号的,这里可以通过消息回复,获取本公众账号下的OpenID,带入回调中,与另一个OpenID进行关联也可以使用开放平台的UnionID功能来得到用户在自己账号下的OpenID
https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx8888888888888888&redirect_uri=http://mascot.duapp.com/oauth2.php?userid=oc7tbuPA9BgUCLADib5nB3k2KWWg&response_type=code&scope=snsapi_userinfo&state=1#wechat_redirect

将该链接回复给关注用户,用户点击后,弹出应用授权界面

3. 回调页面得到链接如下,回调url中将包含参数code

http://mascot.duapp.com/oauth2.php?code=00b788e3b42043c8459a57a8d8ab5d9f&state=1
或者 http://mascot.duapp.com/oauth2.php?userid=oc7tbuPA9BgUCLADib5nB3k2KWWg&code=00b788e3b42043c8459a57a8d8ab5d9f&state=1

4. 再使用code换取oauth2的授权access_token

url如下:

https://api.weixin.qq.com/sns/oauth2/access_token?appid=wx8888888888888888&secret=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&code=00b788e3b42043c8459a57a8d8ab5d9f&grant_type=authorization_code

获得授权Access Token:

复制代码
{
    "access_token": "OezXcEiiBSKSxW0eoylIeAsR0GmYd1awCffdHgb4fhS_KKf2CotGj2cBNUKQQvj-G0ZWEE5-uBjBz941EOPqDQy5sS_GCs2z40dnvU99Y5AI1bw2uqN--2jXoBLIM5d6L9RImvm8Vg8cBAiLpWA8Vw",
    "expires_in": 7200,
    "refresh_token": "OezXcEiiBSKSxW0eoylIeAsR0GmYd1awCffdHgb4fhS_KKf2CotGj2cBNUKQQvj-G0ZWEE5-uBjBz941EOPqDQy5sS_GCs2z40dnvU99Y5CZPAwZksiuz_6x_TfkLoXLU7kdKM2232WDXB3Msuzq1A",
    "openid": "oLVPpjqs9BhvzwPj5A-vTYAX3GLc",
    "scope": "snsapi_userinfo,"
}
复制代码

5. 再使用授权Access Token获取用户信息

url如下:

https://api.weixin.qq.com/sns/userinfo?access_token=OezXcEiiBSKSxW0eoylIeAsR0GmYd1awCffdHgb4fhS_KKf2CotGj2cBNUKQQvj-G0ZWEE5-uBjBz941EOPqDQy5sS_GCs2z40dnvU99Y5AI1bw2uqN--2jXoBLIM5d6L9RImvm8Vg8cBAiLpWA8Vw&openid=oLVPpjqs9BhvzwPj5A-vTYAX3GLc

返回如下

复制代码
{
    "openid": "oLVPpjqs9BhvzwPj5A-vTYAX3GLc",
    "nickname": "刺猬宝宝",
    "sex": 1,
    "language": "zh_CN",
    "city": "深圳",
    "province": "广东",
    "country": "中国",
    "headimgurl": "http://wx.qlogo.cn/mmopen/utpKYf69VAbCRDRlbUsPsdQN38DoibCkrU6SAMCSNx558eTaLVM8PyM6jlEGzOrH67hyZibIZPXu4BK1XNWzSXB3Cs4qpBBg18/0",
    "privilege": []
}
复制代码

获取用户信息完成。

最终得到用户信息如下所示

此方法详细过程可参考 微信公众平台开发(71)OAuth2.0网页授权

这种方法适合,

1. 在朋友圈中获得用户的信息.

2. 在网页中获得用户信息。

3. 在自定义菜单中获得用户信息。

需要说明的是,如果在已经有OAuth2.0网页授权权限的服务号中用这种方法,会自动转换成方法三中的那样,没有“微信登录”提示框出来。

可以微信扫描下面的二维码,然后回复“授权”体验这样的获取方式。

 

三、通过OAuth2.0方式不弹出授权页面获得用户基本信息

1. 配置回调域名

2. 构造请求url如下:

https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx8888888888888888&redirect_uri=http://mascot.duapp.com/oauth2.php&response_type=code&scope=snsapi_base&state=1#wechat_redirect

页面URL中的

scope=snsapi_base 表示应用授权作用域为 不弹出授权页面,直接跳转,只获取用户openid

3. 返回回调页面如下

http://israel.duapp.com?code=02a9bed29b2185a9f0ed3a48fe56e700&state=1

这里获得到了code

4. 再使用code获取OpenID

url如下:

https://api.weixin.qq.com/sns/oauth2/access_token?appid=wx8888888888888888&secret=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa&code=02a9bed29b2185a9f0ed3a48fe56e700&grant_type=authorization_code

返回如下

复制代码
{
    "access_token": "OezXcEiiBSKSxW0eoylIeAsR0GmYd1awCffdHgb4fhS_KKf2CotGj2cBNUKQQvj-oJ9VmO-0Z-_izfnSAX_s0aqDsYkW4s8W5dLZ4iyNj5Y6vey3dgDtFki5C8r6D0E6mSVxxtb8BjLMhb-mCyT_Yg",
    "expires_in": 7200,
    "refresh_token": "OezXcEiiBSKSxW0eoylIeAsR0GmYd1awCffdHgb4fhS_KKf2CotGj2cBNUKQQvj-oJ9VmO-0Z-_izfnSAX_s0aqDsYkW4s8W5dLZ4iyNj5YBkF0ZUH1Ew8Iqea6x_itq13sYDqP1D7ieaDy9u2AHHw",
    "openid": "oLVPpjqs9BhvzwPj5A-vTYAX3GLc",
    "scope": "snsapi_base"
}
复制代码

5. 然后获取全局Access Token【以下与方法一中相同】

https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET

返回结果:

{
    "access_token": "NU7Kr6v9L9TQaqm5NE3OTPctTZx797Wxw4Snd2WL2HHBqLCiXlDVOw2l-Se0I-WmOLLniAYLAwzhbYhXNjbLc_KAA092cxkmpj5FpuqNO0IL7bB0Exz5s5qC9Umypy-rz2y441W9qgfnmNtIZWSjSQ",
    "expires_in": 7200
}

6. 再使用全局ACCESS_TOKEN获取OpenID的详细信息

https://api.weixin.qq.com/cgi-bin/user/info?access_token=ACCESS_TOKEN&openid=OPENID

返回如下:

复制代码
{
    "subscribe": 1,
    "openid": "oLVPpjqs2BhvzwPj5A-vTYAX4GLc",
    "nickname": "刺猬宝宝",
    "sex": 1,
    "language": "zh_CN",
    "city": "深圳",
    "province": "广东",
    "country": "中国",
    "headimgurl": "http://wx.qlogo.cn/mmopen/JcDicrZBlREhnNXZRudod9PmibRkIs5K2f1tUQ7lFjC63pYHaXGxNDgMzjGDEuvzYZbFOqtUXaxSdoZG6iane5ko9H30krIbzGv/0",
    "subscribe_time": 1386160805
}
复制代码

成功获得用户基本信息。

这种适合已经有OAuth2.0网页授权的服务号在网页中使用,且不会弹出“微信登录”页面。减少给用户的打扰。

 

四、使用哪种方法最合适

供参考

1. 服务号
有高级接口权限:  消息回复中三种都可以   自定义菜单中使用方法三 (招商银行信用卡中心使用方法三,康盛微社区使用方法二)
没有高级接口权限: 消息回复中使用方法二   自定义菜单中使用方法二 (没有高级权限需要借用别人的Appid和AppSecret)
2. 订阅号
已认证有获取用户信息权限    消息回复中使用方法一   自定义菜单中使用方法二    (没有高级权限需要借用别人的Appid和AppSecret)
未认证没有获取用户信息权限    消息回复中使用方法二  自定义菜单中暂无方法     (没有高级权限需要借用别人的Appid和AppSecret,方倍工作室使用的就是这种)

 

五、内容更新及源码下载

本节最新的教程说明及源代码已在《微信公众平台开发最佳实践》一书中发布,欢迎购买。

点此购买《微信公众平台开发最佳实践》

定时crontab - 小白的分享

mikel阅读(918)

来源: 定时crontab – 小白的分享

启用 crontab:
crontab -e

查看 crontab -l

删除 crontab -r

进入Vi输入i进入编辑模式
编辑一个定时
00 */1 * * * curl http://we7.yoby123.cn/xxx.php

退出esc 输入:wq

* 表示可能的值
, 表示取值 1,2,34,5
– 表示范围 1-5
/ 表示频率 /10 每十分钟 按分钟

1.png

OAuth2授权原理 - neutra - 博客园

mikel阅读(730)

来源: OAuth2授权原理 – neutra – 博客园

  最近在做第三方接入的,初步定下使用OAuth2协议,花了些时间对OAuth2的授权方式做了些了解。

我还记得一两年前,跟一位同事聊起互联网时,当时我说过一个想法:

目前不少较为稀有的资源,很多都是论坛提供下载的,论坛提供的下载往往要求一个论坛帐号,更有甚者,需回帖才可见,又或者下载需要消耗一定的虚拟货币,而这些货币可以用论坛活跃度而获得。假设现在我是一个普通用户,我要找某个资源。通过搜索引擎或者资料,我发现在某个论坛有这个资源下载,从其他地方获得这个资源代价比较高或者说根本就找不着。当我准备下载时,很可能就被提示需登录后才可下载,随机被跳转到注册页面。

为了这个资源注册一个帐号?我想,无论谁在99%的情况下都不乐意去注册一个只是用一次的帐号,偏偏有些论坛就是为了某些原因要求你必须提供一个帐号。好吧,像我这样的人,当然是瞎填点信息注册个帐号了事。至于注册了帐号需不需要金币或者多少声望才能回帖下载之类的,这里就不唠叨了。这个过程的关键点是:我为了一个临时性的需要,注册了一个永久性无关痛痒的帐号,这个帐号使用一次之后,基本上失去价值了。有无数无聊的用户花了N多的时间在M多的论坛里注册了N*M个无用帐号,这个过程除了对某些统计指标有利以外,对用户没有任何价值。

可不可以做一个平台,使任意用户可以在任意论坛注册一个帐号,随后这个帐号和密码自动登记到这个平台中作为公共帐号,之后,其他用户再访问这个论坛时,就无需再次注册帐号了,直接在这个平台上,自动地使用公共帐号去做该做的事。这样,随着用户数的增加,最终可以达到一个比较理想的情况:大部分论坛的临时性操作,用户都不用再去注册了,也不用担心自己的常用帐号密码等信息泄漏的问题。尽管对于一些有“经济系统”的论坛(需要通过活跃度/发帖数/现金等有偿获得虚拟货币,存在消费行为),这个平台可能不适合,但即使需求只被解决了一半,也是个有价值的产品。

当时只是大概聊了下,完全没有动手的打算,至今我还没发现类似的产品,不知是这个需求不够大众还是什么。那时我也大概看了下OpenID,跟我的设想不一样,OpenID是将一个用户在某个平台上的帐号,公开给其他网站使用,当然公开的只是帐号而不会包含密码。当时宣传的口号大概是这样的:“一次登录,到处使用”。当时我只在豌豆网注册了一个OpenID试着玩玩,感觉支持这个OpenID的资源网站太少了,那个帐号作用不大。

OAuth最近几年大行其道,很大程度得益于微博的推广。OAuth和OpenID是比较容易混淆的两个东西,比较“官方”的观点认为:OpenID设计目的是“身份校验”;OAuth的设计目的是“授权”。我也比较认同这个观点,但我觉得这种说法本身也挺容易混淆,有位同事说“身份校验”本身就是对“用户资源”权限的授予,所以OAuth包含了OpenID的作用。

在说明我的观点之前,不妨思考下,目前提供OAuth的网站有那些,他们的提供的服务是什么,为什么他们大多都提供OAuth却鲜有提及OpenID?(我不是暗指腾讯啦)。

 

OAuth与OpenID

先看看OpenID,前面多少也讲过了,下面以豌豆网为例:
服务提供方:豌豆网
提供的服务:用户身份识别,同一个用户有同一个OpenID描述,帐号密码验证功能由豌豆网提供
服务消费方:第三方
消费的目的:让豌豆网的用户来操作自己网站所拥有的资源
再来对比OAuth,用新浪微博为例吧:
服务提供方:新浪微博
提供的服务:读取/发送/查询微博,好友关系处理等,帐号密码资源都由新浪微博提供
服务消费方:第三方
消费的目的:为终端用户操作该用户在新浪微博的资源提供可能
一对比,区别就很明显了:OAuth和OpenID的区别主要是服务提供方是否提供有价值的资源。
作为一个拥有资源的服务提供方,当然希望自己管理自己的用户信息。假如新浪微博支持其他网站的OpenID登录,由于有不少的OpenID服务提供方,那么它需要如何管理自己的用户呢?例如,用户A通过网站X的OpenID登录新浪微博,跟用户A通过网站Y的OpenID登录新浪微博,最终的效果是一个帐号还是两个帐号呢?如果用户A在新浪微博本身有一个帐号的话,情况又更复杂了。要么所有帐号都按新帐号处理,要么提供多个帐号关联功能。前一种方案简单易行,但产生了大量非活跃帐号,用户体验也不见得好。后一种方案,想一想都觉得,维护是个灾难。于是,大多数的资源提供方都倾向与自己管理自己的用户信息,对于第三方的接入,开放一些授权给他们参与一些用户资源的访问就是了,于是便提供OAuth服务而不是提供OpenID接入,一些网站如腾讯还在 OAuth上提供了OpenID。写着写着,我自己都觉得OpenID的“接入”和”服务”很拗口。好吧,OpenID的接入是说使用其他网站所验证的帐号信息,OpenID的服务是指对外提供OpenID的身份校验服务。
把上面的情况循环循环再循环,最终,一方面,拥有有价值资源的网站,都做OAuth去了,他们在等待开发者和其他第三方网站的接入,壮大他们的平台;另一方面,提供OpenID服务的小网站,几乎没有大网站的接入支持,对用户的吸引力越来越小,典型的恶性循环。然后,大部分网站的OAuth服务虽然基本是按照官网规范做接口,但不少细节都做了个性化。例如部分网站的expires_in单位是秒,部分是用分做单位的。部分网站支持state作为状态传递,部分又不支持。最终这些非标准的东西,会惹恼苦逼的开发者(为什么我会很自然的想起IE?),相信很多开发者都会根据市场份额去选择几个流行的OAuth提供方进行兼容,其他的,见乔布斯去吧。而用户则会根据应用的数量去选择平台,又一个恶性循环。如果你的资源不够吸引开发者,就不会有人愿意为你的自定义标准买单。莫非这就是传说中的,合久必分分久必合?嗯,扯远了。
我并没有贬OpenID褒OAuth的意思,只是觉得在目前市场下,不太可能有大网站愿意放弃提供OAuth服务而使用OpenID接入外部帐号。其实我对OpenID了解不多,写着写着,没想到竟然写了一大坨,我真怀疑自己是不是话痨…… 有点晚,明晚继续,if有空的话。

OAuth授权流程

OAuth2是从OAuth发展而来的,虽然不向下兼容,但了解OAuth能更好的理解OAuth2的一些改变。
OAuth里存在三个主要角色:用户、服务提供方和服务消费方。不少文档会把服务消费方说成是客户端,对于SP来说,这个说法没什么问题,但我感觉这个说放容易引起混淆,所以我这里还是用服务消费方来描述。按流行的口号,服务提供方一般对外宣称自己是某某某开放平台,而服务消费方则是各种第三方应用。用户在平台上有一些已有资源,如好友关系,照片等。

几乎所有的OAuth平台都有类似的背景:他们原先积累了一大堆的真实用户,在互联网开放的趋势下,主动或被动的需要支持第三方应用的接入。第三方应用为了使其功能更加丰富完整,希望从平台能获取甚至操作当前用户的资源。用户很可能不希望第三方得知他原有的帐号和密码,原因很明显,安全考虑嘛。服务提供方也不希望第三方直接使用用户的帐号和密码登录平台操作用户数据,为啥?不便于数据统计和维护嘛,希望对 哪个第三方操作哪个用户数据 和 哪个用户操作自己的数据 两种处理流程有所区别。第三方很无辜,经常大喊“我觉不会使用任何途径存储用户的帐号!”。即使真有人相信这些誓言,但也很难确保第三方使用帐号敏感数据时,不被第四方所捕获,所以,认真你就输了。

为了解决上面的问题,准确的说是让三种角色互相信任,OAuth由此而生。在没有第三方的情况下,服务提供方和用户可以认为是互相信任的,因为用户用域名来确保自己访问的是一个受信的站点;服务提供方则要求用户登录,并且登录会话可以控制。

应为第三方一般是不知名的,用户很难区分第三方合不合法,所以用户需要通过服务提供方来证实第三方,例如位于服务提供方的OAuth授权页面会简单的介绍该应用的简单介绍,正是这些介绍使得用户可以相信,该应用是一个合法登记的第三方。

为了让服务提供方信任第三方应用,第三方应用在必要时需要向服务提供方提供身份凭据。最简单的办法就是第三方开发者去服务提供方那去注册个帐号,然后在需要时用这个帐号来证明自己的身份。这种第三方应用的帐号,下面统称应用帐号。由于第三方的请求不会有人工的干预,所以应用帐号的帐号密码一般由服务提供商提供,方便服务提供方管理,安全系数也较高,因为服务提供方可以制定规则,使密码更难以伪造或猜测。

按理说,第三方应用除了到SP处申请一个应用帐号外,也有其他办法证实自己的身份。

例如可以使用HTTPS连接,让“第四方”去证明。OAuth2使用的就是HTTPS连接,但也仅仅是服务端认证,客户端并不做保证。估计一个方面的原因是,应用的数量很多,一般都是中小规模开发商开发的,客户端也要认证的话,证书申请门槛较高,一个账号密码可以解决的问题有必要去申请证书吗?另一方面是,很多应用是没有服务端的,使用双向HTTPS认证无疑将这些应用拒之门外。

上面的方法是,用户通过服务提供方,去识别第三方是否合法。还有种方式是:服务提供方通过用户,去识别第三方是否合法。但OAuth里没有这种方式的体现,但OAuth2里有类似的方式,那就是提供用户的帐号密码换取AccessToken,名字应该叫“资源所有者密码凭据”。如果第三方应用只是开发者自娱自乐的小应用,这种方式是最简单的。

经过上面的注册和授权流程,用户和服务提供方都可以确认第三方应用的身份了,那第三方如何确认服务提供方和用户的身份?

第三方应用怎么确认服务提供方的身份呢?很简单,域名就是服务提供方的唯一标识,只要DNS不被劫持的话。第三方应用根据服务提供方的返回内容确认用户身份,载体是操作令牌AccessToken,为了方便后面统称ATOK,在OAuth里,ATOK的有效期是从用户授权成功,到用户取消授权,对第三方来说,几乎是永久的。至于用户授权之后取消授权,再授权的时候,两次ATOK是否一样,第三方能否处理好这种情况,OAuth里没有提及,看实现者的心情了。

把上面所说的综合在一起,可以得到一个OAuth的雏形版本:

第三方到服务提供方注册个应用帐号,当需要操作用户在服务提供方处的数据时,提供应用帐号密码申请授权,服务提供方将用户引导到授权页面,当授权成功时,服务提供方将对应该用户的ATOK发给应用,随后应用就使用这个ATOK来操作用户数据。

下面新浪微博OAuth的基本流程(其实各平台的流程都一样,贴这个是觉得这张图比较好看):

从图中可以看到OAuth的流程比原先设想的雏形多了不少东西,这些多出来的有什么作用呢?

  四个步骤

OAuth授权分四步。

第一步,应用向服务提供方申请请求令牌(Request Token),服务提供方验证通过后将令牌返回。这个步骤由于涉及到应用帐号密码,在应用的服务端发起,所以这个步骤对用户透明。

第二步,应用使用请求令牌让浏览器重定向到服务提供方进行登录验证和授权。服务提供方校验请求令牌,将第三方的资料显示给用户,提示用户选择同意或拒绝此次授权。如果用户同意授权,发放已授权令牌并将用户引导到当前应用的注册地址。这个步骤从重定向开始到引导回注册地址之前,应用方并不参与用户身份校验和授权过程,确保第三方不可获得用户的真实帐号密码。

第三步,用已授权令牌向服务提供方换取ATOK。第三方应用需在服务端发起请求,用帐号密码和上一步的令牌换取ATOK,这个步骤对用户而言也是透明的。如果前两步分别是让服务提供方认证应用和用户,那这步就是用户和服务提供方再次认证第三方应用。因为用户浏览器将第二步的结果重定向到第三步,除非用户DNS被劫持,否则就能确保重定向到的是合法的地址。曾经我很困惑在用户授权之后为何不直接返回ATOK而需要再次换取,估计是出于对ATOK的安全考虑,用户浏览器一端存在太多的可能性让ATOK泄漏,最安全的办法还是让第三方服务端来获取和保管ATOK。

第四步,用ATOK作为令牌访问受保护资源。很多时候,权限是有多种类别的。ATOK包含了某个用户对某个应用的授权凭据,准确的说,ATOK对应用户授权时所赋予的一系列权限的集合。所以在这一步,除了校验ATOK的合法性之外,服务提供方还需对该ATOK是否拥有足够的权限执行被保护操作进行判断。

  单次签名

在OAuth里,OAuth的相关请求都要做单次签名,目的是防止OAuth的请求被篡改和重放。签名当然是拿应用帐号的密码来做签名,其实就是对HTTP请求中所有OAuth相关的参数都连在一块,使用密码计算某种哈希值作为签名。OAuth规范里描述了签名的规则,那是相当的繁琐、复杂,足以吓跑一大堆未经世事的开发者。随便找一个OAuth开放平台的API文档,我相信在OAuth授权流程有接近一半会在描述怎么产生签名构造一个合法的HTTP请求。有一对文字图片描述还不够,各开放平台几乎无一例外地提供各种开发语言下的SDK,为求尽量降低技术门槛。即使如此,不少开发者依然觉得,OAuth的签名过程实在是太复杂了,而这些复杂也没有带来预期的好处。

  重定向地址

为了防止有攻击者伪造重定向地址骗取用户授权,服务提供方应对授权时的重定向地址进行验证。所以注册时,第三方应提供重定向地址。服务提供方可以直接对重定向地址进行等值判断,但这样的话就没办法让第三方在授权过程中传递状态,只能借助Cookie/Session之类的方式了。服务提供方也可以判断重定向地址是否同一个域,这样的话应用方就可以在URI里传递少量状态。对于一些没有服务端的第三方Web应用,由于代码是公开的,将应用的帐号密码存在页面里并不合适。OAuth则建议不使用重定向地址,让用户在授权后,把授权码人工输入到应用中进行下一步。记得有段时间FaWave也是这么添加新帐号的。

  安全漏洞

OAuth曾爆了一个安全漏洞,攻击者利用此漏洞可骗取用户信任获取非法的授权。

这个网页有该漏洞的详细说明,流程如下:

简单的说,这个漏洞主要的关键是:

1. 部分服务提供方并未对重定向地址进行合法性判断,或者部分第三方的重定向地址会根据URI的参数再次重定向从而被攻击者利用;

2. RequestToken从未授权到已授权的状态转变时没有变化,从而为攻击者暴力访问回调地址骗取ATOK提供可能;

对于第一点,攻击者伪造重定向地址,即可骗得用户对可靠第三方的授权,获得ATOK

对于第二点,假如第一点不成立,那攻击者可以用第一步的请求令牌构造一个合法的重定向请求,并在用户授权之后、浏览器重定向到合法重定向地址之前,进行同样操作执行这个重定向操作,此时就看攻击者和正常授权流程就存在竞争关系。如果第三方先处理攻击者的请求,攻击者就获得了最终的ATOK。

为了解决上述安全漏洞,OAuth更新了1.0a版本,主要改变就是第一步增加对重定向地址的签名,和第二步与第三步之间增加一个随机校验码,使之与未授权的RequestToken有所区分。

目前大部分的平台都转到了OAuth2。OAuth2虽并不兼容OAuth1,但基本原理是一样的。

 

OAuth2的改变

OAuth2对比OAuth1,主要改变有下面几点:

1. 取消繁琐的签名,全部改用HTTPS。

2. ATOK从原来的永久令牌变为临时令牌,增加RefreshToken

3. 取消获取RequestToken的步骤

4. 提供了多种场景的授权流程

  HTTPS

OAuth原有的签名算法实在是太繁琐了,吓跑了不少开发者。对于服务提供方,也很不好实现,特别是单次签名的实现,由于服务提供方要确保每次由客户端生成的随机码不被重复利用,必须存储每次请求发来的随机码,无论是对存储还是校验都是一个难题。通常的做法是,存储一段时间的随机码,这个时间需比RequestToken的过期时间要长。这样即使到时还有重放攻击,RequestToken也已经失效。

OAuth2取消了签名,改用HTTPS来加密,确保通信内容不被第三方窃取。这个改变毫无疑问是降低了门槛,授权的流程被简化了。虽有少量人有异议,但OAuth2最大的异议是临时的ATOK。

  ATOK与RefreshToken

由于第三方应用往往不重视ATOK的安全性,开发者为图方便经常把ATOK从后端发给前端页面或者存在cookie中。由于OAuth1中ATOK几乎是永久性的,即使发现ATOK被盗用,也只能让用户取消授权,这可能会造成一些其他的问题。OAuth2将ATOK改为临时令牌,当ATOK过期后,需要使用RefreshToken重新获取新的ATOK,让开发者郁闷的是,RefreshToken也不是永久性的,不同的服务提供方有不同的过期时间,相同的是,过期时间都不会太长,顶多也就几个月。

这个改变对很多第三方应用是个坑爹的改变,原本他们几乎都是拿ATOK作为OpenID来使用的(所以才有了各种ATOK被盗用的隐患),而到了OAuth2,ATOK已经不能唯一标识一个用户了,他们要多做很多的东西才能维持用户的身份,在使用ATOK访问用户资源时,步骤也是异常繁琐。

虽然临时ATOK这个改变很合理,但对开发者很不友好,今后会不会继续改变,可以拭目以待。我个人觉得,这个问题其实是另外一个问题,那就是开发者对用户帐号信息的安全意识太单薄,后面讲OAuth的问题时再详细讨论。

  授权流程

OAuth1流程比较复杂,尽管规范里有对多种场景的授权流程进行不同的建议,但很多应用和开放平台最终都使用了同一种授权流程,结果产生了安全隐患(例如上面重定向地址的问题吗)。OAuth2描述了四种授权场景,为这些场景下的授权流程提供指导。我只简单说些要点和差异,详细的说明还是看官方文档和各开放平台的文档稳妥些。

(待续)

脑子是个好东西,我希望机器都能有一个

mikel阅读(885)

来源: 外挂与AI?这是个问题_Gad-腾讯游戏开发者平台

脑子是个好东西,我希望机器都能有一个

作者: 尹宁

1.世界尽头与冷酷的电脑

庞大的野兽曾在这世间漫步,巍然如山。
但现在它们只剩尸骨琥珀。
连最强大的物种也敌不过时间。
你的梦想都被遗忘,恐惧都被磨灭,你的尸骨将成为尘土。
而在尘土之上,一位新的神明将会漫步。
因为这个世界并不属于你,也不属于之前来过的那些。
这里属于尚未到来的那个“人”。

如果世界有尽头的话,以人类目前的想象力来说,世界尽头里一定少不了人工智能:猩红废墟里伫立的终结者,或者是雪白的山脉下掩藏的秘密实验室,又或者是漫天黄沙覆盖的潘多拉星球上留下的神秘碑文。我们总能在游戏中、电影中,回忆起属于人工智能的那一个个画面。这是一个让导演编剧们又爱又恨、让吃瓜群众们既恐惧又向往、让科学家们既激动又不安的名词。就连地球上最权威的科学家霍金、和最成功的企业家埃隆马斯克,也在公开场合表达了对人工智能技术发展的悲观和担忧。

人工智能的定义可以分为两部分,即“人工”和“智能”。“人工”比较好理解,争议性也不大;关于什么是“智能”,就问题多多了。这涉及到其它诸如意识(consciousness)、自我(self)、心灵(mind)等等问题。人唯一了解的智能是人本身的智能,但是我们对我们自身智能的理解都非常有限,所以也就很难定义什么是“人工”制造的“智能”了。在目前的阶段下,普遍定义的智能主体是指一个可以观察周遭环境并作出行动以达致目标的系统。人工智能目前在计算机领域内,得到了广泛的发挥,例如在机器人、经济政治决策、控制系统、仿真系统中。通俗一点的描述就是可以用来炒股、开车、买菜等等。1000个人心目中有1000个人工智能。作为人类的另一个大脑,人工智能的应用场景千姿百态。

不过这篇文章要说的是:人工智能与游戏的结合。

用人工智能去玩游戏?这就好像是和心仪的美女在酒店打上一晚上的LOL,是不是有点大材小用?况且游戏中的AI,能叫人工智能吗?

让我们把时钟调回1998年的夏天。那一年我还在上初中,游戏主机和手机并没有普及。接管了一切娱乐活动的圣地——路边小网吧还处在奔腾2的时代。我们用win95启动电脑,带着从音像店淘来的藏经阁光盘安装游戏,目不转睛地盯着17寸的特丽珑crt显示器。在那个鼠标还是机械滚轮的年代,我们玩《星际争霸》、《红色警戒》、《雷神之锤》。那时候甚至还没有像样的网络游戏。19年以后我已经很难记起那时的细节。在模糊的印象里,只记得在局域网匹配不到玩家的日子里,是一个个虚拟的对手陪伴我度过了美好的游戏时光。

它们有许多名字:200%的电脑、冷酷的电脑、电脑(令人发狂的)。我曾经一度把挑战7家冷酷的电脑视为人生的最高目标,并为此苦练技术。纵使失败让人沮丧,但胜利之后的快感却让人无法自拔,生命仿佛融进了游戏里,一点点被吞噬。

现在,我们管它们叫游戏AI。不太智能,但不可或缺。

2.AI在游戏中能干什么?

游戏中有多种乐趣——关于闯关成功的乐趣、关于练级打宝的成长的乐趣、关于交友、恋爱、贸易的社交的乐趣、关于做有趣任务和在游戏世界中冒险的探索的乐趣、关于PK和攻城的挑战的乐趣——这所有的乐趣AI几乎都可以参与。并且除了扮演对手之外,辅助玩家与提升游戏体验,也是目前AI在游戏中的重要发展方向。

2.1我来组成手部——辅助操作

在游戏的乐趣之中,练级打怪是最没有技术含量的,但恰恰也是占用游戏时间最多的。因此玩家们会想:如果把这些重复性的操作都由机器代劳,游戏会不会更有乐趣?其实在游戏中已经有很多这样的例子如最早期的网游自动寻路、自动交接任务,就引发了一系列核心玩家和休闲玩家的激烈讨论。时至今日,关于内挂、外挂、甚至一系列放置系游戏的争论都没有结束。但毫无疑问的一点是,取代人类的重复性操作本身就是人工智能发展的一个目的。自动驾驶如此,游戏更是如此——愿泡菜和斯金纳盒离我们远去。

让游戏的操作失去乐趣的,可能不仅仅是重复,过高的操作难度也是一种可能性。其中最典型的代表可能就是格斗游戏了。

很久以前,我是一个mugen的爱好者。这是一个包含了几乎所有2d横版格斗游戏的模拟器,并且玩家可以自定义其中的几乎一切元素:背景、特效、角色、AI等等。在人工智能概念还不像现在这样振聋发聩的时候,你可能无法想象每天花大量时间坐在电脑前,看着电脑控制的人物这样打来打去的乐趣在哪里。但实际上的情况是,对于一个操作不那么好,无法打出华丽连招的手残玩家来说,看着电脑中的角色自行对战,可能会比亲自上阵更有乐趣。并且电脑玩家所能做到的不仅仅是互相对打那么简单,铁壁防御、极限反杀、从不失误的连招、乃至角色背景故事和行为特色所带来的各种“梗”,都让我对这个游戏乐此不疲。

整个游戏中的角色行为都是基于行为树所决定的。严格意义上来说这并不是当代的人工智能,顶多只能算是打电脑罢了。但有趣的地方在于电脑之间,相同水平的AI对战的结果并不固定。这让整个观战的乐趣更上了一层楼。如果能加入自我学习的要素,不断提高电脑的水平,那可以说和真正的人工智能只有一步之遥了。

这个游戏设计的初衷只是想把所有2D游戏的角色放在一起进行大乱斗。结果发展到现在,AI对战成为了主流,玩家之间的较量从比拼反应和操作变成了比拼策略和排兵布阵。尤其是在如今手游明显弱化操作门槛的情况下,我认为以后甚至会发展出一种的专门的游戏类型,即玩家只需要定制策略的格斗游戏。

类似的例子还有单机游戏《龙腾世纪》。这也是一款评价非常高的角色扮演游戏。游戏的战斗系统需要玩家同时控制4个角色,并且还是实时进行的——想象一下在《魔兽世界》中一次控制一整个队伍的感觉。如果你是一个动作游戏爱好者,也许还有可能爱上这种设计;但对于操作和反应慢一点的玩家而言,这简直是一个噩梦。于是游戏贴心地提供了队友AI的设置功能。玩家可以根据角色的职业和技能设置一套完整的决策树,其条件和行为的选择复杂程度远超当时的同类型游戏。游戏中还有AI的解锁和升级功能,随着游戏进程可以解锁更多的条件设置和相关选项。

举个例子:当自身魔法值大于50%,己方战士血量小于50%,同时身边敌人数量大于3,并且自身周围没有可打断职业时,对战士释放治疗术

虽然大大减少了操作流程,但游戏玩法还是得到了保证的,玩家依然要决定做什么,只是操作的过程由机器代劳。从这个方面来看,电脑确确实实解放了人工。毕竟,反应速度和运算能力就是计算机的强项。而纵观游戏发展的历史,许多电子游戏的玩法也都脱胎于体育运动和桌面游戏,其优势也就在于利用计算机的性能,把原本纸、笔和掷骰子的工作接管了而已。在这个阶段,AI可以说只是个工具,更快地完成了玩家的操作,决策还是由玩家自己下达的。

2.2我来组成头部——辅助决策

脑子是个好东西,可不是人人都有。当你踌躇满志准备大杀四方时,你断网了,于是你的人物变成了一个没有脑子的行尸走肉坑死了队友;当你观看一个卡牌游戏的比赛但却又不能像职业选手一样记住牌表和概率时,你智商下线了,无法和身边的美女谈笑风生。生活中总是有许多这样的困境,当你在面对一个陌生的游戏环境不知所措时,AI恰到好处地在暗处探出了头,像一道光。

起初,只是简单的记录和分析。记牌器、胜率分析、概率表、提示,并没有什么大问题。

而在加入了分析计算和海量的大数据之后,事情开始起了变化——玩都玩了,干脆把数据记下来吧——记都记了,干脆所有玩家的数据分析一下吧——分析都做了,干脆给你个最优解吧——最优解都有了,干脆帮你操作吧——然后呢?然后就没有然后了。大部分游戏其实就是一个解决问题的过程,而AI最擅长的就是解决问题。

所以许多人已经预见到未来的游戏会是什么样子的了。既然有了玩家的海量数据,通过分析可以轻易地给出推荐,例如Dota和LOL中可以基于大数据的分析来推荐英雄搭配(Dota2已经实装)。此外,还可以在升级技能的时候给出建议,甚至自动加点。如果更夸张点,路过草丛和野区的时候会提示,前方草丛有74.5%的概率藏匿着敌人,不插眼的人有61%都被gank了。20分钟还没出辉耀的幽鬼82.3%都输了,赶紧打钱去吧。

这些还并非严格意义上的人工智能,仅仅是辅助操作和大数据分析的结果。如果再加上目前主流方向的模式识别、深度学习工具呢?

 

2.3我来组成这个世界——强人工智能

不知大家能否感觉到,当你沉溺于游戏的时候,这个世界的很多“可能性”也就随之而关闭。无所事事地走在街上,打开无聊的电视,与无趣的人交谈,翻开低俗的报纸,买回千篇一律的好莱坞大片,等等等等,这些行为表面上都不如游戏那样有趣,但它们却会为你的生活创造各式各样的“机会”:未来永远是新奇的,充满了变数。但是在网游中,尤其在练级打宝的过程中,除了经验值,什么也沉淀不下来,时间就像气泡一样幻灭。

但是如果游戏中的AI除了解决问题之外,还能提供真实的情感反馈,并满足玩家的社交需求时,甚至整个游戏世界都能因为玩家的行为而产生真正的变动时,所有的剧情不再是精心设计的体验,而是什么都有可能发生的未知数时,那么这一切关于游戏的评论都将改变。游戏将成为真正意义上的第二人生。再加上虚拟现实、体感交互等技术,到那时在游戏里找个AI女朋友也不再是痴人说梦。

3.一切只是因为人们喜欢用外挂

如果说游戏总喜欢游走在科技发展的最前沿,那么外挂,也偏爱驻足在游戏发展的最前沿,它的发展早已越来越科技向:从早期直接修改游戏数据,到现在模拟操作、替代决策等。有兴趣的同学不妨去看看目前主流游戏的付费外挂,已经发展到了什么水平。

在《魔兽世界》中,辅助工具已经高度模块化,并且实现了独立开发:

l  如果你要练级:加载PVE战斗模块、任务模块和地图寻路模块。人物会自动做任务练级。

l  如果你要打战场:加载PVP战斗模块、战场模块。人物会自动打战场,甚至还可预设战场的战术细节。

l  如果你要经商:加载采集模块、拍卖行模块。设置好相应的细节,角色就会自动采集,做买卖。

l  甚至可以选择性加载。比如仅仅开启自动战斗,在战场里手动走路和选择进攻点。曾经还有同事开玩笑说,魔兽世界如果去掉复杂的战斗,化身为点点鼠标即可完成的轻度游戏,搞不好更受欢迎。

在以电子竞技闻名的《星际争霸2》中,外挂除了在操作上碾压人类选手之外,不仅可实现自动闪现、躲避、造兵,甚至在战术选择上也能给出建议,自动完成自动骚扰、侦查等。又如《守望先锋》,最近也因为外挂问题深陷舆论漩涡。因为外挂和AI的界限越来越模糊,并且不再采用修改数据的做法,故而也导致反外挂工作也越来越困难。

在我看来,外挂和AI的区别并不在于目的和功能上的不同。因为功能多寡仅受技术水准的高低所限,而从目的性的角度考虑,外挂和AI的本质都是一样的——解决问题。

传统的游戏AI应用把大问题拆分成了许多小问题,并试图解决。

我要玩得爽:——

l  如何快速升级

l  如何出装备

l  如何打怪

l  如何华丽出招

l  如何选择策略

外挂是把所有问题十分功利地归结成了一个大问题。

我要玩得爽:——

l  我要赢

因此对于AI的应用和外挂,其最大的区别在于:

1)     是否造成了不公平的游戏体验;

2)     游戏的乐趣本身有没有被破坏。

在电子竞技如火如荼的今天,无法保证公平性的游戏往往走不长远。合理、公平地使用AI也是技术开发者们需要考虑的课题。而关于游戏乐趣本身,真正优秀的游戏,乐趣并不全部来自于赢得胜利。毕竟逃也可以逃得漂亮,输也可以输得荡气回肠。弱化游戏的功利性,和设计多样化的胜负条件,或许才是我们需要考虑的方向。

 

4.关于梦想

Deepmind的下一个目标是《星际争霸2》。看起来,AI接管游戏并没有我们想象的那么遥远。比起围棋,除了策略上的选择之外,AI的优势还在于完成游戏里不可思议的复杂操作。如果规则不加以限制,我认为AI会赢得毫无悬念。而至于赢了之后会怎么样,后文有述;

只是我一直有个梦想,这个梦想却随着科技发展而不断进化。今天它会是这样的一种可能:我带着一张拷贝着最新游戏AI的512兆U盘,乘坐时间机器返回1998年,在学校后门的网吧里不紧不慢地坐下。加载AI,点上一根烟,单手操作鼠标来玩《红色警戒》、《星际争霸》或是《雷神之锤》之类的其他什么游戏。我完全可以预见到,成群结队的人在身后观摩着我的表演。他们的心脏无法承受如此剧烈的冲击,像被枪击般一排排倒下。勉强站立的人们面色潮红,手脚都在瑟瑟发抖。全校的女生一瞬间为我而情愫盛放,飞吻声连成一片,如雷作响——她们争风吃醋,只为亲吻我的手背和白色的鼠标。我将成为那个时代最伟大的魔法师、电竞之王、游戏的皇帝,何等的虚荣!

嗯,脑子是个好东西。但不一定非得是自己的,不是吗?

 

5. 回答一些你关心的问题

Q1:游戏中AI应用会朝着什么方向发展而去?

A:大概有三个阶段:

一:基于AI托管所衍生的新的玩法——体育类、动作类、RTS等强操作型的游戏会分支出与迥然不同的模式:

你掉线后由聪明的AI接管是现阶段设计者和用户的痛点,自然会最先应用到产品中;

当AI与高段位玩家的实操几近相似,托管将变成此类游戏里的一项功能,能让你随时随地让AI代替自己做重复性事务,甚至在一些关键点交给AI看起来会更保险;

随着AI的不断迭代演化,它开始在进程中不断学习“主人”的操作和意识习惯,对这个哪怕是犯错都模仿得惟妙惟肖的AI,你当真不会产生兴趣?

于是不知从何时起,训练AI成为大多数品类产品中的一项养成要素,因为这个与你貌合神不离的影子将会需要之时助上一臂之力,哪怕那些已嗅到商机的策划们,也开始让你为提升AI段位时要付出额外的代价;

最终,在养兵千日且师出有名的战役里,你不再需要猪一样的队友,而是将与熟悉你每一个走位意图、深谙你每一下虚晃套路的AI一起并肩作战,来打败对面同等阵容的玩家。

二:而游戏之外也在演化,在电子竞技的直播观战的看台上,就如同前不久那万众瞩目一战成名的AlphaGo,越来越多电竞项目的人机对战、人机配合对战都会引来额外热度——无论是竞技人,还是围观者,都在愈发精彩绝伦的比赛中探寻人工与智能之间的难分难解,都在看似无穷无尽的图灵测试中屏息拉锯、肆意狂欢。

三: 再之后,也许游戏制作者也厌倦了日复一日年复一年的码农搬砖,开始让AI学会随意利用引擎接口构建或离奇或恢弘的场景;学会根据大数据筛选和编撰人们喜闻乐见的游戏音乐、角色性格和世界观; 学会在人类浩瀚历史长河中引经据典出任务关卡设计的套路、学会在深不见底的数值汪洋里活用每一个正态分布……最终它将学会让人忘却时间而沉迷,或条件反射的付费。而游戏公司也再不必担心玩家会透支游戏内容,因为AlphaGame它丫的日以继夜迭代起版本来,连加班费都不用付。

So,我们游戏制作者就失业了?图样图森破,深圳科兴的午夜依旧灯火通明楼下照样的士成群,作为尚未被结束的进程树之一,你我总会有冥冥中的kpi要完成的不是?

 

被你发现了,这一切的一切,只是源于我们喜欢用外挂。

Q2: 这么屌的外挂在哪弄?

A:请联系作者。

(本文出自VR新观察)

LuManager忘记后台登陆密码怎么办?_曾海森_新浪博客

mikel阅读(1236)

LuManager忘记后台登陆密码怎么办?_曾海森_新浪博客,曾海森,

来源: LuManager忘记后台登陆密码怎么办?_曾海森_新浪博客

用请phpMyAdmin用root用户登陆,然后找到LuManager数据库的lu_users表,再找到相应的用户,如zijidelu,然后修改password字段内容为dd8eb031789b6a0664709455e7d512ce即可,即将密码还原为zijidelu。如果有设置问题验证,请将question和hash_answer字段清空

注:新版LUM已经做了设置,IP:8888/PM登录显示:The URL is wrong.提示
需要先登录SSH,输入下面的命令,才能够登录phpMyAdmin管理:

ln -s /usr/local/LuNamp/pm /usr/local/LuManager/pm 

支付宝AR抢红包?前端轻松就破解~ - vajoy - 博客园

mikel阅读(1083)

来源: 支付宝AR抢红包?前端轻松就破解~ – vajoy – 博客园

近期阿里搞了各LBS+AR实景的红包玩法,小伙伴们在公司里都玩疯了~

有时候为了抢一个红包,会跑到另一个地方去拍照,虽然略麻烦,但整体的互动还是很有意思的。

不过对于机智的前端童鞋来说,只需要简单的一段代码就能破解AR红包(当然成功率也不是100%)

破解原理见《上线仅一天:支付宝AR红包惨遭技术流破解》,感谢这位设计师童鞋。

我们要做的事情其实很简单 —— 把系统自带的小横条都去掉,去掉的部分取其附近的图片内容来填充,最终得到的效果图有不小的几率会被识别为匹配成功:

对于上图中间那块区域,我们可以通过固定的轮廓对底图进行遮罩得出。

所以对于前端而言,我们可以通过这样的 DOM 结构来实现如上需求:

其中 C 和 B 其实是同一个背景(即抢红包页面的手机截图),A 是一个遮罩轮廓,会对 B 进行剪辑获得非条纹部分的图片内容。同时 B 再相对 C 进行垂直偏移,用自身被剪辑后的内容挡住 C 的条纹。

根据图片alpha通道来做遮罩的能力,我们可以使用 CSS3 的 mask-image 特性来实现,其具体应用在我之前《巧用 mask-image 实现简单进度加载界面》一文中已做了详细介绍:

本文不再赘述该 CSS3 特性。

另外还有一点小需求 —— 希望 B 和 C 的底图可以动态更换。这个我们使用 input[type=file] 组件来实现即可。

直接贴代码吧:

复制代码
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        div {
            margin-top: -1500px;
            position: relative;
            overflow: hidden;
            background: #EEE;
            width: 1440px;
            height: 2110px;
        }

        #bg, #mask-bg {
            position: absolute;
            width: 1440px;
            height: 2560px;
            background-size: cover;
        }
        #mask-bg{
            top:9px;
            mask-image: url(mask.png);
            -webkit-mask-image: url(mask.png);
        }
        input {
            height: 60px;
            margin-top: 20px;
        }
    </style>
</head>
<body>
<div>
    <p id="bg"></p>
    <p id="mask-bg"></p>
</div>
<input type="file">

<script>
    var input = document.querySelector('input'),
        bg = document.querySelector('#bg'),
        maskBg = document.querySelector('#mask-bg');

    input.onchange = function () {
        var src = getObjectURL(this.files[0]);
        setBg(src);

    };

    function setBg(src){
        bg.style.backgroundImage = 'url(' + src + ')';
        maskBg.style.backgroundImage = 'url(' + src + ')';
    }

    /**
     * 通过选择的文件获取其图片路径(blob)
     * @param file
     * @returns {*}
     */
    function getObjectURL(file) {
        var url = null;
        if (window.createObjectURL != undefined) {
            url = window.createObjectURL(file)
        } else if (window.URL != undefined) {
            url = window.URL.createObjectURL(file)
        } else if (window.webkitURL != undefined) {
            url = window.webkitURL.createObjectURL(file)
        }
        return url
    }

</script>
</body>
复制代码

需要了解的是,我们在 getObjectURL 方法中使用了 URL.createObjectURL 接口来为所选文件生成对应的 blob 内容的URL,再将其赋给底图的 background-image。其格式是这样的:

最终整体效果如下:

 

需要注意的是,这里的图片宽高值,以及遮罩图 mask.png,都是根据我的手机分辨率来定制的,所以要使用该工具的话请自行修改样式和遮罩图片。

该小工具挂在我的 github 仓库上,有需求的可以自助下载修改。

lanmp 服务器 的php-fpm is stop! 问题恢复

mikel阅读(973)

php-fpm is stop! 问题恢复

1.先查看下问题,查看lnmp的服务状态

/root/lnmp status

 

=========================================================================
=========================================================================
Manager for LNMP V1.1  ,  Written by Licess
=========================================================================
LNMP is a tool to auto-compile &amp; install Nginx+MySQL+PHP on Linux
This script is a tool to Manage status of lnmp
For more information please visit http://www.lnmp.org

Usage: /root/lnmp {start|stop|reload|restart|kill|status}
=========================================================================
nginx (pid 13725 13724 13723 13722 13721 13719 13718 13717 13716) is running...
php-fpm is stop!
SUCCESS! MySQL running (13688)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address               Foreign Address             State
tcp        0      0 0.0.0.0:80                  0.0.0.0:*                   LISTEN
tcp        0      0 0.0.0.0:62288               0.0.0.0:*                   LISTEN
tcp        0      0 0.0.0.0:3306                0.0.0.0:*                   LISTEN
tcp        0      0 :::62288                    :::*                        LISTEN

解决方法:

1.重启php-fpm 就行了

单独重启nginx或者mysql、php:
nginx : kill nginx进程ID,再/usr/local/nginx/sbin/nginx
mysql :/etc/init.d/mysql restart
php:没有重启
phpfpm:/usr/local/php/sbin/php-fpm reload

2.重启后,过段时间又访问不了,再重启下lnmp

/root/lnmp restart

LNMP安装了哪些软件?安装目录在哪? - LNMP一键安装包

mikel阅读(1077)

来源: LNMP安装了哪些软件?安装目录在哪? – LNMP一键安装包

LNMP一键安装包除去安装所必须的依赖包,还会默认安装以下软件: Nginx、MySQL/MariaDB、PHP、phpMyAdmin、Zend Optimizer/Zend GuardLoader。用户可以根据自己的需要安装其他组件,如FTP服务器、缓存组件,也可以使用升级脚本对Nginx、MySQL、PHP进行升级。
安装这些组件或升级都需要在lnmp下载解压缩后的目录,比如下载到/root目录,就进入/root/lnmp1.2-full目录,执行以下命令。

虚拟主机管理:

    参见:

http://lnmp.org/faq/lnmp-vhost-add-howto.htmlFTP服务器:

  • 可选1,PureFTPd,执行:./pureftpd.sh 安装,http://yourIP/ftp/ 进行管理。
  • 可选2(LNMP1.2下已经移除该脚本),Proftpd,执行:./proftpd.sh 安装,执行命令:/root/proftpd_vhost.sh 添加FTP账号。

缓存加速:

    LNMP1.2及更高版本统一使用./addons.sh 进行安装和卸载。 使用方法:./addons.sh {install|uninstall} {eaccelerator|xcache|memcached|opcache|redis|imagemagick|ioncube} 详细教程:

http://lnmp.org/faq/addons.html

    LNMP1.1下:

  • 可选1,eAccelerator,执行:./eaccelerator.sh 安装。
  • 可选2,memcached,执行:./memcached.sh安装。
  • 可选3,xcache,安装时需选择版本和设置密码, http://yourIP/xcache/ 进行管理,用户名 admin,密码为安装xcache时设置的。执行:./xcache.sh安装。
  • 可选4,redis,执行:./redis.sh安装。
  • 可选5,opcache,执行:opcache.sh安装。http://yourIP/ocp.php 进行管理。Zend Opcache与eaccelerator相冲突,需卸载eaccelerator。

LNMP1.2及更高版本:
统一使用./upgrade.sh 进行升级工作。
使用方法:./upgrade.sh {nginx|mySQL|mariadb|m2m|php|phpa}
详细教程:http://lnmp.org/faq/lnmp1-2-upgrade.html

LNMP1.1下:

升级脚本:

  • Nginx升脚本可,升级至任意Nginx版本。执行:./upgrade_nginx.sh 按提示进行升级。
  • PHP升级脚本,可升级至大部分PHP版本。执行:./upgrade_php.sh 按提示进行升级。
  • MySQL升级脚本,可升级至任意MySQL版本,MySQL升级风险较大,虽然会自动备份数据,建议自行再备份一下。执行:./upgrade_mysql.sh 按提示进行升级。
  • MySQL升级至MariaDB,可从MySQL升级至Mariadb,虽然会自动备份数据,建议自行再备份一下。执行:./upgrade_mysql2mariadb.sh 按提示进行升级。
  • MariaDB升级脚本,可升级已安装的Mariadb,虽然会自动备份数据,依然建议自行再备份一下。执行:./upgrade_mariadb.sh 按提示进行升级。
  • LNMPA PHP升级脚本,可升级LNMPA的PHP至大部分版本。执行:./upgrade_lnmpa_php.sh 按提示进行升级。

图像处理:

  • 可选1,imageMagick,执行:./imageMagick.sh 安装。
    执行:./imageMagick.sh 安装,imageMagick路径:/usr/local/imagemagick/bin/。

解密:

  • 可选1,ionCube,执行:./ionCube.sh 安装。

其他:

  • 可选1,执行:./php5.2.17.sh 可安装一个不与LNMP冲突的PHP 5.2.17单独存在,使用时需要将nginx虚拟主机配置文件里的 php-cgi.sock 修改为 php-cgi52.sock。
  • 可选2,执行:./reset_mysql_root_password.sh 可重置MySQL/MariaDB的root密码。
  • 可选3,执行:./check502.sh 可检测php-fpm是否挂掉,502报错时重启,配合crontab使用。
  • 可选4,执行:./cut_nginx_logs.sh 日志切割脚本。
  • 可选5,执行:./remove_disable_function.sh 运行此脚本可删掉禁用函数。

LNMP相关软件安装目录
Nginx 目录: /usr/local/nginx/
MySQL 目录 : /usr/local/mysql/
MySQL数据库所在目录:/usr/local/mysql/var/
MariaDB 目录 : /usr/local/mariadb/
MariaDB数据库所在目录:/usr/local/mariadb/var/
PHP目录 : /usr/local/php/
PHPMyAdmin目录 : 0.9版本为/home/wwwroot/phpmyadmin/ 1.0及以后版本为 /home/wwwroot/default/phpmyadmin/ 强烈建议将此目录重命名为其不容易猜到的名字。phpmyadmin可自己从官网下载新版替换。
默认网站目录 : 0.9版本为 /home/wwwroot/ 1.0及以后版本为 /home/wwwroot/default/
Nginx日志目录:/home/wwwlogs/
/root/vhost.sh添加的虚拟主机配置文件所在目录:/usr/local/nginx/conf/vhost/
PureFtpd 目录:/usr/local/pureftpd/
PureFtpd web管理目录: 0.9版为/home/wwwroot/default/ftp/ 1.0版为 /home/wwwroot/default/ftp/
Proftpd 目录:/usr/local/proftpd/
Redis 目录:/usr/local/redis/

LNMP相关配置文件位置
Nginx主配置(默认虚拟主机)文件:/usr/local/nginx/conf/nginx.conf
添加的虚拟主机配置文件:/usr/local/nginx/conf/vhost/域名.conf
MySQL配置文件:/etc/my.cnf
PHP配置文件:/usr/local/php/etc/php.ini
php-fpm配置文件:/usr/local/php/etc/php-fpm.conf
PureFtpd配置文件:/usr/local/pureftpd/pure-ftpd.conf
PureFtpd MySQL配置文件:/usr/local/pureftpd/pureftpd-mysql.conf
Proftpd配置文件:/usr/local/proftpd/etc/proftpd.conf 1.2及之前版本为/usr/local/proftpd/proftpd.conf
Proftpd 用户配置文件:/usr/local/proftpd/etc/vhost/用户名.conf
Redis 配置文件:/usr/local/redis/etc/redis.conf

LNMPA相关目录文件位置
Apache目录:/usr/local/apache/
Apache配置文件:/usr/local/apache/conf/httpd.conf
Apache虚拟主机配置文件目录:/usr/local/apache/conf/vhost/
Apache默认虚拟主机配置文件:/usr/local/apache/conf/extra/httpd-vhosts.conf
虚拟主机配置文件名称:/usr/local/apache/conf/vhost/域名.conf