第 24 章 通过OpenID进行登录

OpenID是一种网上身份识别服务,它的目标是让用户可以网上使用同一身份登录不同的系统。

这一章我们讲解如何使用Spring Security支持OpenID。

24.1. 配置

首先在pom.xml中添加使用OpenID所需的依赖。

<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-openid</artifactId>
  <version>3.1.3.RELEASE</version>
</dependency>
        

然后在xml中添加OpenID所需的配置。

<http>
    <intercept-url pattern="/admin.jsp" access="ROLE_ADMIN" />
    <intercept-url pattern="/**" access="ROLE_USER" />
    <openid-login user-service-ref="userService"/>
</http>

<authentication-manager>
	<authentication-provider>
		<user-service id="userService">
			<user name="http://family168.myopenid.com/" password="password" authorities="ROLE_ADMIN,ROLE_USER" />
		</user-service>
	</authentication-provider>
</authentication-manager>
        

只需要添加openid-login标签,并引用一个userService。userService中需要配置OpenID中的账号,以及对应的权限。它会在用户登录成功后对用户进行授权。

现在我们可以启动应用,进入登陆页面。

登录页面

图 24.1. 登录页面


在登录页面中输入http://family168.myopenid.com/,这是我们已经注册过的一个OpenID账号,点击提交之后会跳转到myopenid.com网站。

myopenid.com

图 24.2. myopenid.com


在此处输入密码:password。登录成功之后就会跳转回我们的系统。

登录成功

图 24.3. 登录成功


这时我们可以看到当前登录系统的用户是http://family168.openid.com/。

24.2. 系统时间问题

因为OpenID服务器会根据当前时间生成nonce进行权限校验,所以一定要保证服务器的当前时间是正确的,如果服务器当前时间比正常时间快了哪怕只是几秒钟,也会导致在进行校验时抛出nonce is too old异常,这会导致一直无法正常登陆。

实例在ch114。

24.3. openid4java的处理流程

在simple-openid下执行mvn jetty:run。启动后在http://localhost:8080/simple-openid/页面中填写http://localhost:8080/simple-openid/user.jsp就可以登录了。

流程序列如下:

在index.jsp填写openid之后,会跳转到consume_redirect.jsp中。,它会获取user.jsp中的XRD信息,获取其中的provider信息。

先使用openid.mode=associate获得签名。

获得openid.signed签名之后,拼装URL,跳转到provider。

http://localhost:8080/simple-openid/provider.jsp
?openid.identity=http%3A%2F%2Flocalhost%3A8080%2Fsimple-openid%2Fuser.jsp
&openid.return_to=http%3A%2F%2Flocalhost%3A8080%2Fsimple-openid%2Fconsumer_returnurl.jsp%3Fopenid.rpnonce%3D2011-04-29T00%253A42%253A38Z0%26openid.rpsig%3DXpFn2uPHElOzK8J0wPJ6UU7QykMdPFUwPHxMTIUZ82U%253D
&openid.trust_root=http%3A%2F%2Flocalhost%3A8080%2Fsimple-openid%2Fconsumer_returnurl.jsp
&openid.assoc_handle=1304037580515-0
&openid.mode=checkid_setup
        
  • openid.identity指的是openid的主体信息。

  • openid.return_to指的认证成功以后的跳转页面。

  • openid.trust_root似乎是信任的网站的URL。(待确认)

  • openid.assoc_handle用户rp和op之间的一个句柄,用来对响应签名。

  • openid.mode是操作的动作,checkid_setup说明间接请求(通过浏览器重定向)验证用户身份。

在OP(OpenID Provider)中,要验证RP发来的return URL是否有效。没问题再判断是否已经登录,如果没有登录,则进入provider_authorization认证流程。在simple-openid中是一个假的页面,直接在session里写了一个标记位,如果实际使用的时候,可以自己实现认证机制。

认证成功之后进入provider页面,provider进行一些清理工作之后就会跳转回returnurl.jsp,并带上很多参数。

http://localhost:8080/simple-openid/consumer_returnurl.jsp
?openid.rpnonce=2011-04-29T01%3A01%3A02Z0
&openid.rpsig=pb0GgswawEnRgzyA7H2ekVBASq2%2B4ZhjTdKU7npYioo%3D
&openid.mode=id_res
&openid.identity=http%3A%2F%2Flocalhost%3A8080%2Fsimple-openid%2Fuser.jsp
&openid.return_to=http%3A%2F%2Flocalhost%3A8080%2Fsimple-openid%2Fconsumer_returnurl.jsp%3Fopenid.rpnonce%3D2011-04-29T01%253A01%253A02Z0%26openid.rpsig%3Dpb0GgswawEnRgzyA7H2ekVBASq2%252B4ZhjTdKU7npYioo%253D
&openid.assoc_handle=1304037580515-0
&openid.signed=return_to%2Cidentity
&openid.sig=glgdZFetZG0%2FGICortpqpq5dpTA%3D
        

rp表示Replying Party就是下游依赖OpenID的子系统。

op表示OpenID Provider提供OpenID应用的系统。

  • openid.rpnonce是时间戳。

  • openid.rpsig是下游系统的签名。(暂时不知道含义)

  • openid.mode是操作的动作,id_res说明是用户认证成功以后的肯定断言。

  • openid.identity是用户主体。

  • openid.return_to是认证成功返回的URL。(这个明显重复了)

  • openid.assoc_handle分配处理?(待确认)

  • openid.signed逗号分隔的签名字段列表?(待确认)

  • openid.sig是BASE64编码的签名封装?(待确认)

RP接收到肯定断言时,也要进行验证,判断return_url与当前的请求URL是否匹配。discover信息与断言信息是否匹配(待确认)。是否是同一个OP返回的。签名字段是否匹配。