- 网上找了半天,参考资料很少,好不容易写了一个,记录下来,
package com.jiuqi.crcc.controller;
import java.net.URLEncoder;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.openid4java.consumer.ConsumerManager;
import org.openid4java.consumer.InMemoryConsumerAssociationStore;
import org.openid4java.consumer.InMemoryNonceVerifier;
import org.openid4java.consumer.VerificationResult;
import org.openid4java.discovery.DiscoveryInformation;
import org.openid4java.discovery.Identifier;
import org.openid4java.message.AuthRequest;
import org.openid4java.message.AuthSuccess;
import org.openid4java.message.MessageExtension;
import org.openid4java.message.ParameterList;
import org.openid4java.message.ax.AxMessage;
import org.openid4java.message.ax.FetchRequest;
import org.openid4java.message.ax.FetchResponse;
import org.openid4java.message.sreg.SRegMessage;
import org.openid4java.message.sreg.SRegResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
*
* <p>
* TODO OpenID认证
* (需要填写loginUrl的具体地址,以及完善returnVerify()方法中的认证通过后的处理)
* </p>
*
* <p>
* Copyright: 版权所有 (c) 2002 - 2008<br>
* Company: 久其
* </p>
*
* @author
* @version
*/
@Controller
@RequestMapping("/openid")
public class OpenIdSecurity {
/*
* 一些专有名词: EU:End User,用户。 RP:Relying Party ,用来代指OAuth2中的受信任的客户端,身份认证和授权信息的消费方;
*
* OP:OpenID Provider,有能力提供EU身份认证的服务方(比如OAuth2中的授权服务),用来为RP提供EU的身份认证信息;
*
* ID-Token:JWT格式的数据,包含EU身份认证的信息。
*
* UserInfo Endpoint:用户信息接口(受OAuth2保护),当RP使用ID-Token访问时,返回授权用户的信息,此接口必须使用HTTPS
*/
// openid认证地址(请求地址)
private String ENDPOINT = "认证地址";
private String loginUrl="填写需要登录的网址";
private static final Logger LOGGER = LoggerFactory.getLogger(OpenIdSecurity.class);
public final ConsumerManager manager = new ConsumerManager();
@RequestMapping("/login")
public void login(HttpServletRequest request, HttpServletResponse response) throws Exception {
// 创建ConsumerManager对象,这个对象是保持与OP端的通信的
if (request.getAttribute("consumermanager") == null) {
ConsumerManager newmgr = new ConsumerManager();
// setAssociations方法设置与OP的关联存放的位置,这里我们将它存放在内存
newmgr.setAssociations(new InMemoryConsumerAssociationStore());
// setNonceVerifier方法设置记录response_nonce的位置。
newmgr.setNonceVerifier(new InMemoryNonceVerifier(5000));
request.setAttribute("consumermanager", newmgr);
}
// 告诉OP认证完成之后返回到哪个URL
// String returnToUrl = "http://https://work.cr23g.com";
String returnToUrl = "http://localhost:7007/openid/return";
// String returnToUrl = "http://jmcauley.ucsd.edu/data/amazon/";
// 对用户提供的标识符执行发现
List discoveries = manager.discover(ENDPOINT);
// 检索一个服务端点进行身份验证
DiscoveryInformation discovered = manager.associate(discoveries);
// 存储在用户Session中发现的 信息
request.getSession().setAttribute("openid-disc", discovered);
// 比较重要,通过关联句柄以及returnURL准备OP需要的参数以及参数值
// 获取要发送到OpenID提供程序的AuthRequest消息
AuthRequest authReq = manager.authenticate(discovered, returnToUrl);
// attribute Exchange获取用户信息:
FetchRequest fetch = FetchRequest.createFetchRequest();
fetch.addAttribute("fullname", "http://openid.net/schema/namePerson/friendly", true);
fetch.addAttribute("email", "http://openid.net/schema/contact/internet/email", true);
// 将扩展附加到身份验证请求
authReq.addExtension(fetch);
// 重定向到OP认证 ENDPOINT
response.sendRedirect(authReq.getDestinationUrl(true));
}
/**
* 验证openid OP便将用户重定向到RP,并发送认证信息给RP,RP需要接受认证信息,检查是否认证通过,获取用户信息,然后进行后续的处理。
*
* @param request
* @param response
* @throws Exception void
*/
@RequestMapping("/return")
public void returnVerify(HttpServletRequest request, HttpServletResponse response) {
String fullname = null;
String email = null;
try {
// 获取ConsumerManager认证对象
ConsumerManager manager = (ConsumerManager) request.getAttribute("consumermanager");
// 获取响应参数列表
ParameterList params = new ParameterList(request.getParameterMap());
DiscoveryInformation discovered = (DiscoveryInformation) request.getSession().getAttribute("openid-disc");
StringBuffer url = request.getRequestURL();
String query = request.getQueryString();
if (query != null && query.length() > 0) {
url.append("?").append(query);
}
// 根据参数列表,关联句柄以及url_query验证是否通过认证
VerificationResult verification = manager.verify(url.toString(), params, discovered);
Identifier verified = verification.getVerifiedId();
if (verified != null) {
AuthSuccess authSuccess = (AuthSuccess) verification.getAuthResponse();
// 两种获取用户属性的方式处理是不同的,所以在return_url中这两种方式都要考虑到
if (authSuccess.hasExtension(SRegMessage.OPENID_NS_SREG)) {
MessageExtension ext = authSuccess.getExtension(SRegMessage.OPENID_NS_SREG);
if (ext instanceof SRegResponse) {
SRegResponse regResp = (SRegResponse) ext;
email = regResp.getAttributeValue("email");
fullname = regResp.getAttributeValue("fullname");
}
} else if (authSuccess.hasExtension(AxMessage.OPENID_NS_AX)) {
MessageExtension ext = authSuccess.getExtension(AxMessage.OPENID_NS_AX);
if (ext instanceof FetchResponse) {
FetchResponse fetchResp = (FetchResponse) ext;
email = (String) fetchResp.getAttributeValues("email").get(0);
fullname = (String) fetchResp.getAttributeValues("fullname").get(0);
}
}
System.out.println(email + ">>>>>>>>" + fullname);
// OpenID中没有提供Email或者姓名信息处理,验证通过跳转页面
if(email==null|email.length()==0) {
}else if(fullname==null|fullname.length()==0){
}else {
//进行url编码,防止特殊字符被转义
email=URLEncoder.encode(email, "UTF-8");
response.sendRedirect(loginUrl + "?email=" + email);
}
// 后续的处理
}
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}
}