Tag Archives: Security

Android 6.0 运行时权限实践要点

Android在6.0之后添加了新的权限管理模型,每个应用必须在原油的Manifest.xml声明的基础上增加运行时的权限申请才能进行相关API的调用,这对终端用户的隐私保护是一大利好,浏览一下国内的很多应用,一个很简单的APP也会申请Contact、Location、ID、SMS、 *History等权限。自从6.0之后App安装完成未启动前你就可以去应用设置中关闭没必要的权限。当然国内的很多定制ROM比如MIUI、EMUI等在之前android版本中已经定制了相关模型,但这一次是从API级别上标准化了这一设置,所有支持后续版本的APP都必须实现这一原则。

相关运行时权限申请开发过程,可通过Android官方网站浏览。更多Android权限相关

这里只说明了几个开发要点:

  • 1、当前流行的运行时权限申请流程有两种:

a)在App启动时强制检测所有预申请权限,有一项必须权限用户没有授权则弹出对话框提示到应用设置页面进行授权打开。

b)在App运行时需要某一项或者多项权限时临时授权,然后继续下一项操作

当前国内应用大多采用a)方法,微信、支付宝采用此方法,可能导致后面一票儿的App采用这种方式,而且有些非必要权限一旦拒绝授权,应用立刻退出,体验相当暴力。Google系、国外其他App大多采用b)方法,非必要情况下不会预先申请授权。

采用a)简单直接但是用户体验相当冲突,尤其是用户拒绝申请授权时,所以建议使用方法b)。

  • 2、多必要权限的同时申请

由于调用ContextCompat.checkSelfPermission()时只能进行一项权限检查导致后续的requestPermissions()虽然方法支持多项权限的申请,但在此情况下只能进行一项权限授权申请,进而导致后续只能在onRequestPermissionsResult()检查第一项权限授权是否通过后再进行下一项授权申请。这其间onResume()调用还需要记录每一项权限的授权结果。

方法:构建一个权限数组,onStart()时每次循环遍历所有预申请权限,如果所有权限均授权通过,则进行下一步操作,如果是未授权,则调用requestPermissions(),如果是拒绝,则提示用户跳转APP设置界面进行授权。在onRequestPermissionsResult()方法中不检查权限的授权结果而是继续调用循环遍历来检查权限授权结果。这里需要注意一个无限循环的问题,如下。

  • 3、权限授权过程无限循环

requestPermissions()调用后弹出的是由PackageManager管理的Dialog主题的Activity(B),如果此时用户屏幕锁屏,B调用onStop(),授权申请Activity(A)调用onStop(),开屏后A将触发onStart()再次调用requestPermissions(),此时B还在前台,再创建B‘实例导致B回调onRequestPermissionsResult()继续重复要点2的逻辑,导致进入无限循环,在API>23后会有多次请求权限授权的日志输出,可以注意观察。为了避免上述情况发生,可以在授权申请Activity(A)添加标记位避免开锁屏时的重复调用或者锁屏后的onStop()中发起取消申请授权,然后在onRequestPermissionsResult()中判断是否要继续调用。

  • 4、取消授权申请

在公开的API中并没有在申请授权过程中的取消操作,因为运行时授权申请本身并不允许并行执行,所以当前状态下只有三种可能性:不再提醒、允许、拒绝。但当出现上述3逻辑时就需要有可以取消的流程。在Activity.java的源码中提供了一种方式:

通过主动调用授权结果返回,然后根据后面两个参数来结束授权流程。

  • 5、Fragment、Activity中的使用

Fragment中直接使用父类的requestPermissions()

Activity兼容模式下调用ActivityCompat.requestPermissions()

  • 6、友好性的授权拒绝提示

微信、支付宝都是采用对话框的方式,但在用户体验上很冲突,推荐采用SnackBar

OAuth2协议和Spring Security OAuth2实现

OAuth2协议在API访问授权中广为使用,Google、Facebook、微博、腾讯的公开API也都使用它。虽然在使用上有些复杂,尤其是服务器端的使用更为繁琐,但它在权限授予、资源访问限制上的优势让其使用广泛。

OAuth2的协议流程如下:

oauth-protocol-flow

以国内的微博为例,

Resource Owner=微博用户;

Client=第三方应用,如Fuubo、Weico;

Authorization Server=微博平台授权服务器;

Resource Server=访问微博、用户信息等资源的服务器

当开发者决定要开发一款基于微博的应用时,需要到http://open.weibo.com去填写一些资料,比如应用名称、类型、访问哪些资源,提交相关信息之后,微博后台会创建应用,分配一个client_idclient_secret,这两个字段对你的应用至关重要,以后会派上用场。

下面就开始正式的OAuth2协议流程:

A、开发者构造Authorization Request(请求微博用户授权),如果此时微博用户A没有登录会直接跳转到微博登录页面,如果已经登录会跳转到授权页面,如图所示。

OAuth2_intro

此时会列出开发者在申请应用时选择要访问的权限,除了必须的权限以外微博用户A可以不勾选部分权限,这样开发者就无法读取相对应的资源。

B、 Authorization Grant(微博用户授予访问权限),如果微博用户A点击“授权”,开发者将获得这个微博用户A的微博、用户信息等资源的访问,开发者将获取到一枚临时code。点击“取消”将拒绝资源的访问。

C、Authorization Grant(请求微博平台授权)开发者拿着微博用户A授权之后获取的临时code,访问微博平台授权服务器,获取“永久”(也有时间限制)访问微博用户A的授权。

D、Get Access Token(微博平台授予微博用户A的访问)微博平台授权服务器检查微博用户A的临时code,检查通过后给开发者返回一个“永久”的Token

E、Take in Access Token(发起携带Token的请求),开发者在访问资源的请求中带上Token

F、Protected Resource(返回微博用户A的微博、用户信息等资源)资源服务器检查Token,根据请求URL的不同返回微博用户A的相应资源信息。

通过这几步就实现了微博用户、微博平台、第三方开发者之间的访问授权,当然如果是用户B使用开发者开发的这款应用还需要进行如上所述的步骤。

以上简单介绍了OAuth协议中最复杂的一种授权访问方式(Authorization Code Grant),也是第三方应用用的最多的一种,其他三种对于特定环境下建议使用,比如:

Implicit Grant-多用于浏览器内的应用,可直接回调获取到Token,简单方便。

Resource Owner Password Credentials Grant-用于第三方应用处于可控的风险之下,多用于内部系统的互访问。

Client Credentials Grant-顾名思义,多用于客户端的授权访问,客户端必须保证在开发者手中。

OAuth2协议的可以访问地址查看。

=========================================================================

Spring在security project的基础上实现了OAuth2 的Server端,同时支持四种授权方式,参考了网上的不同示例但都没有完美支持所有方式,阅读官方文档参考源码后完整构建了OAuth2的Server端。

1、代码示例基于

spring-core v4.2.3

spring-security v3.2.x

spring-security-oauth v2.0.8

2、自定义Endpoint用于回调、跳转、登录等功能:

/login-用户form登录action[POST]

/msg/code-授权回调页

/msg/error-授权访问错误页

/msg/login_success-用户form登录成功回调页

/msg/login_error-用户form登录失败回调页

3、OAuth ClientDetail、Token数据库表脚本

访问地址下载。

4、web.xml中除了Spring基础配置还需要添加Spring Security相关配置

 

5、Spring token存储、读写验证服务。

6、OAuth2授权时拒绝、授权各自不同的Handler以及触发处理

7、用户form登录时成功、失败各自不同的Handler以及触发处理

8、用户form登录filter捕获、安全规则

9、用户认证

10、应用认证filter捕获

11、应用认证服务管理

12、OAuth2认证服务器

至此,Spring OAuth2的基础配置已经完成。在数据库的oauth_client_details中添加demo应用的详细信息,如client_id、client_secret、redirect_uri。

=========================================================================

验证配置过程:

1、用户Form登录:

POST http://example.com/login

username:xxx

password:XXX

2、OAuth2 implicit方式用户授权

GET http://example.com/oauth/authorize?redirect_uri=http://example.com/msg/code&client_id=ccc&response_type=token

3、用户授权回调action(浏览器会直接跳转,若为Rest工具手动执行以下请求)

POST http://example.com/oauth/authorize

user_oauth_approval:true

4、授权成功,回调http://example.com/msg/code#access_token=xxxxxxxxx&&expired_in=48400

注意回调时不会将access_token作为queryParam回调。

如果能够回调成功,说明配置OAuth2配置成功,其他三种方式仅限于2、3、4步的微小区别。

~如上文配置中提到的Auth Decision Manager,上述配置只是完成了Spring OAuth2的基础部分,具体到哪个应用能够访问哪些资源,资源权限的定义规则还没有给出,这就是授权访问中资源服务器的定义了。

相比于PHP、Python对于OAuth2协议的简单实现,Spring的实现略显笨重,配置复杂。Spring自成一体的闭合,将OAuth2基于Security进行实现,而且又对LADP等协议有不同的接驳,这或许也是Spring中间件越做越重的归宿~

当然Java方向上还有一个OAuth2的实现也可以关注,Apache Oltu

tiantongyuan-south

博客正式启动HTTPS服务

博客从今天开始正式迁移至HTTPS服务,虽然国内各种阻挠SSH登录,但还是配置好了。

COMODO Positive SSL+Apache Httpd2.4+Wordpress配置,抽空详细写一下这个过程,在G面前你不得不用各种奇怪的办法曲线救国,实属无奈~

环境:Ubuntu+Apache httpd+Wordpress

写一下具体的步骤:

1、选择SSL证书类型

namecheap上列出了四家证书注册商。以Comodo为例,它提供多达14个类型的证书,证书的差别在是否为单证书认证单域名、单证书认证多级域名,单证书认证多二级域名,多域名认证以及担保金额差异、服务支持差异、是否显示Trust Logo、128bit或者256bit加密区别等等。对于个人博客网站可能只需要单二级域名或者单三级域名的SSL认证,所以使用PositiveSSL、PositiveSSL Wildcard是最佳选择,如果是企业支付、电子商务服务就需要更高级别的SSL证书,nitrohsu.com使用的是PositiveSSL,价格上也是Comodo中最便宜的每年10刀。

2、生成CSR(Certificate Signing Request)

使用OpenSSL生成,键入:

需要输入请求的相关认证信息,

Country Name (2 letter code) [CN]—国家代码
State or Province Name (full name) [Some-State]—省、自治区名称
Locality Name (eg, city) []—城市名称
Organization Name (eg, company) [Internet Widgits Pty Ltd]—公司名称
Organizational Unit Name (eg, section) []—组织名称
Common Name (e.g. server FQDN or YOUR name) []—完整域名
Email Address []—联系邮箱

A challenge password []—密钥挑战码
An optional company name []—可选公司名称

以上的内容如果不存在可以以“NA”代替,一定注意Common Name填写要认证的对应域名,PositiveSSL要填写具体域名“www.nitrohsu.com”,PositiveSSL Wildcard要填写泛域名“*.nitrohsu.com”。

一旦填写完成,会在目录下生成一个“server.key”、“server.csr”,”server/key”用于服务器和客户端会话时解密数据,“server.csr”用于后续的激活认证。

3、Activate SSL

  • 登录Comodo网站,进入Product List,选择SSL Certificates,点击要激活的域名右侧“Activate”;
  • 将第二步中生成的CSR文件中的内容拷贝到CSR Code的位置,下面Primary Domain自动转义出要激活的域名,如果没有转义说明生成的CSR有问题,确认上一步中的Common Name没问题;
  • 点击“submit”,选择DCV(Domain Control Validation)方式,根据自己HTTP Server的便利性选择(注:GeoTrust、Symantec、Thawte OV and EV的SSL不需要此步骤)

1)Email-填写对应认证域名的域邮箱,接收邮件激活;

2)HTTP-将认证文件上传至服务器域指向的根路径;

3)DNS-创建一个新的CNAME认证。

  • 填写相关联系方式、品牌信息,确认填写的信息,点击“submit”会生成一个Certificate ID;
  • 如果需要修改验证方式或者下载相关验证文件,可以点击“Edit Methods”。

4、下载Bundle、CRT文件

  • DCV认证通过后登录Comodo网站,进入Product List,选择SSL Certificates,点击“See Details”;
  • 选择“Download Certificate”,下载的zip包中包含三个文件:

yourdomain_com.ca-bundle

yourdomain_com.crt

yourdomain_com.p7b

5、Apache httpd证书配置

  • 确保Apache httpd开启了mod_ssl模块:

  • /etc/apache2/site-avaliable/下复制default.conf为yourdomain-ssl.conf

  • 添加以下:

键入“a2ensite yourdomain-ssl”,开启HTTPS服务。

6、Rewrite 301

通过以上设置仅仅是将HTTPS服务开启,但是HTTP服务默认还是正常运行,不会跳转到HTTPS服务上面,如果需要301指向HTTPS服务还需要额外的配置。

网站根目录下的.htaccess文件添加以下:

 

7、reload server,访问https://your-domain.com应该就可以了。