首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

使用 Play Framework 和 Scala 管理用户身份验证(3)Silhouette 简介

使用 Play Framework 和 Scala 管理用户身份验证(3)Silhouette 简介

Silhouette 简介 Silhouette 框架的首要特征是灵活性。Silhouette                实现了一组独立的身份验证组件,开发人员需要配置和组合它们来构建身份验证逻辑。主要组件包括:
  • 身份服务:Silhouette                    依靠 IdentityService                    特征的一个实现来处理所有与检索用户相关的操作。通过这种方式,用户管理完全与框架分离开来。UserService                    类(已在 “ ” 一节中介绍)实现一个由 MongoDB                    支持的身份服务。
  • AuthInfoRepository:Silhouette                    需要知道如何持久化用户凭据。该框架将此工作委派给 AuthInfoRepository                    特征的一个实现。该应用程序使用一个综合存储库,其中组合了 PasswordInfoDao 和                    OAuth1InfoDao 类,这两个类都已在 “ ” 一节中介绍。
  • 身份验证器:身份验证器在成功完成身份验证后跟踪用户。它们是存储数据的令牌,比如其有效性状态和用户的登录信息。Silhouette                    拥有基于 cookie、Play 无状态会话、HTTP 标头和 JSON Web Tokens (JWT)                    的实现。
  • 身份验证器服务:每个身份验证器都有一个关联的身份验证器服务,负责身份验证器的生命周期:创建、初始化、更新、续约和过期。
  • 环境:环境定义一个 Silhouette                    应用程序需要的关键组件。它按用户和身份验证器类型(在该应用程序中,为                      中定义的 User 类和一个                    CookieAuthenticator)来进行类型参数化。环境是通过传递身份服务实现                    (UserService) 和身份验证器服务实现来构建的。我使用了                    CookieAuthenticatorService 类,这是                    CookieAuthenticator 类型所需要的。
  • 提供程序:提供程序是一个处理用户的身份验证的服务。该应用程序使用 Silhouette 的                    CredentialsProvider 来执行本地身份验证,还使用了 OAuth1                    TwitterProvider。
  • SocialProviderRegistry:这是该应用程序支持的所有社交服务提供程序的占位符。在本例中,它包含                    TwitterProvider 实例。
配置 Silhouette 组件注意您的 Play 版本 从 2.4.0 版开始,Play Framework                    框架采用了依赖注入作为一种内置机制。旧版本采用了完全不同的机制来将参数传递给控制器。一些库仍无法用于 Play 2.4.x。由于 Play                    相对未成熟,主要版本之间的变化可能非常大。

Silhouette 组件通过依赖注入的方式来配置和组合。Play 使用   作为默认的依赖注入实现。(如果您愿意,可以插入其他实现。)Guice                module.Module 类定义了 Silhouette 需要的绑定,首先是基本声明,如 清单 12 所示。
清单 12. 依赖注入绑定
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Module extends AbstractModule with ScalaModule {

  def configure() {
    bind[IdentityService[User]].to[UserService]
    bind[UserDao].to[MongoUserDao]
    bind[UserTokenDao].to[MongoUserTokenDao]
    bind[DelegableAuthInfoDAO[PasswordInfo]].to[PasswordInfoDao]
    bind[DelegableAuthInfoDAO[OAuth1Info]].to[OAuth1InfoDao]
    bind[IDGenerator].toInstance(new SecureRandomIDGenerator())
    bind[PasswordHasher].toInstance(new BCryptPasswordHasher)
    bind[FingerprintGenerator].toInstance(new DefaultFingerprintGenerator(false))
    bind[EventBus].toInstance(EventBus())
    bind[Clock].toInstance(Clock())
  }
   
  // ... Bindings for Silhouette components follow
}




清单 12 代码定义了 Silhouette                的身份服务;用户、密码和 OAuth1 DAO;以及                Silhouette 的主要组件需要的一些对象的绑定。 清单 13                显示了这些组件的定义,也包含在 module.Module 中。
清单 13. 依赖注入绑定(续)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
@Provides def provideEnvironment(
    identityService: IdentityService[User],
    authenticatorService: AuthenticatorService[CookieAuthenticator],
    eventBus: EventBus): Environment[User, CookieAuthenticator] = {
  Environment[User, CookieAuthenticator](identityService, authenticatorService, Seq(), eventBus)
}

@Provides def provideAuthenticatorService(
    fingerprintGenerator: FingerprintGenerator,
    idGenerator: IDGenerator,
    configuration: Configuration,
    clock: Clock): AuthenticatorService[CookieAuthenticator] = {
  val config = configuration.underlying.as[CookieAuthenticatorSettings]("silhouette.authenticator")
  new CookieAuthenticatorService(config, None, fingerprintGenerator, idGenerator, clock)
}

@Provides def provideCredentialsProvider(
    authInfoRepository: AuthInfoRepository,
    passwordHasher: PasswordHasher): CredentialsProvider = {
  new CredentialsProvider(authInfoRepository, passwordHasher, Seq(passwordHasher))
}

@Provides def provideAuthInfoRepository(
  passwordInfoDAO: DelegableAuthInfoDAO[PasswordInfo],
  oauth1InfoDAO: DelegableAuthInfoDAO[OAuth1Info]): AuthInfoRepository = {
   new DelegableAuthInfoRepository(passwordInfoDAO, oauth1InfoDAO)
}

@Provides def provideTwitterProvider(
    httpLayer: HTTPLayer,
    tokenSecretProvider: OAuth1TokenSecretProvider,
    configuration: Configuration): TwitterProvider = {
  val settings = configuration.underlying.as[OAuth1Settings]("silhouette.twitter")
  new TwitterProvider(httpLayer, new PlayOAuth1Service(settings), tokenSecretProvider, settings)
}

@Provides def provideOAuth1TokenSecretProvider(
    configuration: Configuration, clock: Clock): OAuth1TokenSecretProvider = {
  val cfg = configuration.underlying.as[CookieSecretSettings]("silhouette.oauth1TokenSecretProvider")
  new CookieSecretProvider(cfg, clock)
}

@Provides def provideSocialProviderRegistry(
    twitterProvider: TwitterProvider): SocialProviderRegistry = {
  SocialProviderRegistry(Seq(twitterProvider))
}




Environment(它通过一个 CookieAuthenticator 来验证                User 实例)通过以下实体来实例化:
  • 一个绑定到 UserService 类的 IdentityService
  • 一个绑定到 CookieAuthenticatorService 的                    AuthenticatorService
  • 一个空的请求提供程序列表(本应用程序中未使用)
  • 一个 EventBus,可用于广播身份验证事件(本应用程序中未使用)
CredentialsProvider 通过注入一个由                DelegableAuthInfoRepository 实现支持的                AuthInfoRepository 来创建,而该实现将凭据持久化任务委派给                PasswordInfoDao 和 Oauth1InfoDao                类。TwitterProvider 类需要 OAuth1TokenSecretProvider                特征的实现,该实现定义如何在 OAuth1 运行期间持久化令牌机密。最后,应用程序定义了一个                SocialProviderRegistry,其中列出了 TwitterProvider                作为唯一可用的社交服务提供程序。
Silhouette 配置文件 cookie 身份验证器服务、Twitter 提供程序和 OAuth1 令牌机密提供程序的绑定访问在 conf/silhouette.conf                文件中定义的配置属性(如                    清单 14 所示),该文件包含在主要 conf/application.conf                文件中(参见  )。
清单 14. Silhouette                配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
authenticator.cookieName="authenticator"
authenticator.cookiePath="/"
authenticator.secureCookie=false
authenticator.httpOnlyCookie=true
authenticator.useFingerprinting=true
authenticator.authenticatorIdleTimeout=30 minutes
authenticator.authenticatorExpiry=12 hours

oauth1TokenSecretProvider.cookieName="OAuth1TokenSecret"
oauth1TokenSecretProvider.cookiePath="/"
oauth1TokenSecretProvider.secureCookie=false
oauth1TokenSecretProvider.httpOnlyCookie=true
oauth1TokenSecretProvider.expirationTime=5 minutes

twitter.requestTokenURL="https://api.twitter.com/oauth/request_token"
twitter.accessTokenURL="https://api.twitter.com/oauth/access_token"
twitter.authorizationURL="https://api.twitter.com/oauth/authorize"
twitter.callbackURL="http://dwdemo.com:9000/auth/social/twitter"
twitter.consumerKey=${?TWITTER_CONSUMER_KEY}
twitter.consumerSecret=${?TWITTER_CONSUMER_SECRET}




请参阅   查看这些属性的详细解释。可以注意到,其中使用了                TWITTER_CONSUMER_KEY                和 TWITTER_CONSUMER_SECRET 环境变量来避免在源代码中公开 OAuth1 机密。
安全操作 Silhouette 定义了两个对实现受保护的请求处理函数很有用的临时操作。这些操作可用于 Silhouette                控制器特征中包含的控制器组合:
  • UserAwareAction:此操作可以由经过身份验证的用户执行。该操作收到的请求将具有一个                    Option[U] 类型(对于一些依赖于应用程序的用户,类型为 U)的                    identity 属性,如果请求是经过身份验证的用户发出的,将会定义该属性。
  • SecuredAction:此操作必须由经过身份验证的用户执行。否则,它将调用应用程序的错误处理函数的                    onNotAuthorized 方法(在我的应用程序中,它重定向到登录页面,如 “ ” 一节中所述)。此操作设置了一个类型为 U                    的请求 identity 属性(对于一些依赖于应用程序的用户,类型为 U),如                        清单 15                            所示。清单 15. Silhouette                            中受保护的请求
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class ApplicationController extends Silhouette {
      def someUserAwareAction = UserAwareAction.async {implicit request =>
        request.identity match {
          case None => // Request sent anonymously ...
          case Some(u) => // Request sent by authenticated user u
        }
      }
       
      def someSecureAction = SecureAction.async { implicit request =>
        logger.info(s"Logged user: ${request.identity}")
        ...
      }
    }




返回列表