首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

《Spring Security3》第八章第二一部分翻译(OpenID用户的注册)

2012-08-27 
《Spring Security3》第八章第二部分翻译(OpenID用户的注册)?OpenID用户的注册问题?o.s.s.openid.OpenIDAuth

《Spring Security3》第八章第二部分翻译(OpenID用户的注册)

?

OpenID用户的注册问题


?o.s.s.openid.OpenIDAuthenticationFilter负责监听/j_spring_openid_security_check这个URL并响应用户的登录请求,类似于UsernamePasswordAuthenticationFilter为/j_spring_security_checkURL所作的那样。从这个图我们可以看到o.s.s.openid.OpenID4JavaConsumer委托openid4java库构建最终重定向用户到OpenID提供者的URL。openid4java库(通过org.openid4java.consumer.ConsumerManager)还负责查找提供者,对此我们前面有所描述。


?我们可以看到用户在提交凭证到OpenID提供者站点后,被重定向到/j_spring_openid_security_check。OpenIDAuthenticationFilter进行一些基本的检查以判断这个请求是OpenID请求(从JBCP Pets登录表达发起)还是一个提供者的合法OpenID响应。

<h1>Or, Register with OpenID</h1><p> Please use the form below to register your account with OpenID.</p><form action="j_spring_openid_security_check" method="post"> <label for="openid_identifier">Login</label>: <input id="openid_identifier" name="openid_identifier" size="50" maxlength="100" type="text"/> <img src="images/openid.png" alt="《Spring Security3》第八章第二一部分翻译(OpenID用户的注册)"/> <br /> <input type="submit" value="Login"/></form>

?这个表单实际上与登录页的表单完全一样。那我们怎样区分登录和注册请求呢?

区分登录和注册请求

package com.packtpub.springsecurity.security;// imports omittedpublic class OpenIDAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler { @Override public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { if(exception instanceof UsernameNotFoundException && exception.getAuthentication() instanceof OpenIDAuthenticationToken&& ((OpenIDAuthenticationToken)exception.getAuthentication()).getStatus().equals(OpenIDAuthenticationStatus.SUCCESS)) { DefaultRedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); request.getSession(true).setAttribute("USER_OPENID_CREDENTIAL", ((UsernameNotFoundException)exception).getExtraInformation()); // redirect to create account page redirectStrategy.sendRedirect(request, response, "/registrationOpenid.do"); } else { super.onAuthenticationFailure(request, response, exception); } }}

?我们可以看到这个代码扩展了父类的默认行为,在满足以下条件时将重定向用户到registrationOpenid.do:

这个代码将OpenID提供者返回的OP-LocalIdentifier值设置到session中,所以在被重定向到OpenID注册URL时还能取到。

配置自定义的认证失败处理器

<openid-login authentication-failure-handler-ref="openIdAuthFailureHandler"><!-- The corresponding bean can be declared in dogstore-base.xml:--><bean id="openIdAuthFailureHandler" value="/login.do"/></bean>

?defaultFailureUrl是用户遇到真正的登录失败时(如提供了非法的凭证信息),用户被重定向到的地址。

添加OpenID注册功能到控制器上

@RequestMapping(method=RequestMethod.GET,value="/registrationOpenid.do")public String registrationOpenId(HttpServletRequest request) { String userId = (String) request.getSession().getAttribute("USER_OPENID_CREDENTIAL"); if(userId != null) { userService.createUser(userId, "unused", null); setMessage(request, "Your account has been created. Please log in using your OpenID."); return "redirect:login.do"; } else { setMessage(request, "Please register using your OpenID."); return "redirect:registration.do"; }}

????????? 接下来,我们要修改IuserService接口和UserServiceImpl实现来建立一个简单的createUser方法:

@Servicepublic class UserServiceImpl implements IUserService { @Autowired CustomJdbcDaoImpl jdbcDao;// existing code omitted @Override public void createUser(String username, String password, String email) { jdbcDao.createUser(username, password, email); }}

@Transactionalpublic void createUser(String username, String password, String email) { getJdbcTemplate().update("insert into users(username, password, enabled, salt) values (?,?,true,CAST(RAND()*1000000000 AS varchar))", username, password); getJdbcTemplate().update("insert into group_members(group_id, username) select id,? from groups where group_name='Users'", username);}

?你可能对SQL感到熟悉——这就是我们在第四章:凭证安全存储中原来初始化用户的。还记得我们创建DatabasePasswordSecurerBean再启动时为密码加salt?有了createUser方法,我们可以移除启动SQL了并且使用Java来初始化用户——你觉得我们应该怎样写代码来完成它呢?你为什么不试一试呢——这是一个很有效的练习来测试你对这方法的知识。

public class CustomJdbcDaoImpl extends JdbcUserDetailsManager implements IChangePassword {

?这会需要对UserServiceImpl做一些小的修改:

@Overridepublic void createUser(String username, String password, String email) { GrantedAuthority roleUser = new GrantedAuthorityImpl("ROLE_USER"); UserDetails user = new User(username, password, true, true, true, true, Arrays.asList(roleUser)); jdbcDao.createUser(user);}

?你可以看到有两种不同的方式注册用户,自定义和内置的。每种方法都能有效的处理OpenID注册问题。尽可以体验实例应用并选择你喜欢的方法。

???????? 一旦用户通过我们的IuserService功能建立,用户被重定向到首页并且可以登录了。如果你想增强用户体验,我们可以做一些代码修改,保持OpenIDAuthenticationToken到重定向并自动认证用户。

?

【注意,OP-Local identifiers可能会很长——实际上,OpenID 2.0规范并没有提供OP-Local identifier的一个最大长度。Spring Security默认的JDBC数据库模式提供了一个相对很小的用户名列(你可能会记得我们将它从默认值扩展到了100个字符)。取决于你的需要,你可能愿意进一步扩展用户名列以容纳长的标识,或者实现OpenID处理链上的子类(如OpenIDAuthenticationProvider或UserDetailsService)以正确处理太长的标识符。这可能包括将用户名拆为多列或存储被删节的URL和完整URL的哈希值。

要记住的是,认证不仅仅是基于OpenID标识数据库中的用户。有一些使用OpenID的站点比这更进一步,允许关联OpenID标识符和要进行认证的用户名(例如,允许多个OpenID关联相同的用户账号)。根据用户名提取出OpenID对于那些拥有不同提供者的多个OpenID且想在站点中使用的用户来说会有用——尽管这在一定程度上违背了OpenID的初衷,但它确实存在,你在设计使用OpenID站点的时候需要记住。】

?

???????? 除了凭证管理和中心认证,OpenID的另一个承诺就是对用户来说在一个地方管理其个人信息并对特定的站点有选择的释放信息。这可能会提供能够丰富的注册体验。让我们看一下属性交换期望如何解决这个问题。

热点排行