我在 servlet 中使用 openid4java。我有两个 servlet - 一个执行第一步(将用户重定向到登录/接受应用程序访问),第二个处理结果信息
在文档中,写到 org.openid4java.consumer.ConsumerManager 类在两个步骤中必须是相同的实例。我可以为此创建单例吗?它是线程和请求安全的吗?
感谢您的回复!
我在 servlet 中使用 openid4java。我有两个 servlet - 一个执行第一步(将用户重定向到登录/接受应用程序访问),第二个处理结果信息
在文档中,写到 org.openid4java.consumer.ConsumerManager 类在两个步骤中必须是相同的实例。我可以为此创建单例吗?它是线程和请求安全的吗?
感谢您的回复!
在来自官方 openid4java 示例的消费者 servlet 中,ConsumerManager 似乎是线程安全的——它们对所有会话使用单个 ConsumerManager 实例。我也以这种方式使用它,还没有注意到任何奇怪的行为。但是来自开发人员的关于线程安全的 javadoc 声明会很棒......
//目前仅与 google 合作 // 试试这个 - 这就是一个..
导入 java.io.IOException;
导入 java.net.MalformedURLException;
导入 java.net.URL;
导入 java.util.List;
导入 javax.servlet.ServletConfig;
导入 javax.servlet.ServletContext;
导入 javax.servlet.ServletException;
导入 javax.servlet.http.HttpServletRequest;
导入 javax.servlet.http.HttpServletResponse;
导入 org.apache.commons.logging.Log;
导入 org.apache.commons.logging.LogFactory;
//import org.jboss.web.tomcat.security.login.WebAuthentication;
导入 org.openid4java.OpenIDException;
导入 org.openid4java.consumer.ConsumerException;
导入 org.openid4java.consumer.ConsumerManager;
导入 org.openid4java.consumer.VerificationResult;
导入 org.openid4java.discovery.DiscoveryInformation;
导入 org.openid4java.discovery.Identifier;
导入 org.openid4java.message.AuthRequest;
导入 org.openid4java.message.AuthSuccess;
导入 org.openid4java.message.ParameterList;
导入 org.openid4java.message.ax.AxMessage;
导入 org.openid4java.message.ax.FetchRequest;
导入 org.openid4java.message.ax.FetchResponse;
公共类 OpenAuth 扩展 javax.servlet.http.HttpServlet {
最终静态字符串 YAHOO_ENDPOINT = "https://me.yahoo.com";
最终静态字符串 GOOGLE_ENDPOINT = "https://www.google.com/
帐户/o8/id";
//更新版本的示例代码来自:
https://crisdev.wordpress.com/2011/03/23/openid4java-login-example/
//在此处添加您的 servlet 脚本路径 - 所以如果身份验证失败或
成功它将执行操作 - 在 doGet 中检查以下内容
公共字符串 scr="/servlets/MyServlet";
私有 ServletContext 上下文;
私人 ConsumerManager 经理;
私人 ConsumerManager 杂志;
//Vahid Hedayati 更新的代码 http://pro.org.uk
//删除配置初始化 - 将帖子移动到 doGet - 因为之前的代码
要求它是一个帖子,但也需要包含标识符作为
网址
//标识符也是用于标识符代码的相同变量 -
//清理以产生不同的变量并减少混乱
//doGet identifer 更改为 openid_identifier 并且现在看起来
对于 openid_username 这是从返回的默认变量
openid 选择器
//http://groups.google.com/group/openid4java/browse_thread/thread/
5e8f24f51f54dc2c
//读完上面的帖子 - 将管理器存储在会话对象中
雅虎身份验证失败我更改了经理的代码
//管理
公共无效doPost(HttpServletRequest请求,HttpServletResponse
响应) 抛出 ServletException,IOException {
doGet(请求,响应);
}
protected void doGet(HttpServletRequest req, HttpServletResponse
resp) 抛出 ServletException, IOException {
//新变量
Stringouser=(String)req.getParameter("openid_username");
如果(用户==空){用户=“”;}
//mage如果是openid_consumer_manager的session值
null 它会生成一次
//并且在代码中调用管理器的地方首先返回
经理通过查找会话价值来评估
mag=(ConsumerManager)req.getSession().getAttribute("open_id_consumer_manager");
如果(mag==null){
this.manager = new ConsumerManager();
req.getSession().setAttribute("open_id_consumer_manager", manager);
}
String identify=(String)req.getParameter("openid_identifier");
if (identify==null) { identify="";}
如果(!identify.equals(“”)){
this.authRequest(识别,用户,req,resp);
}别的{
//如果他们成功了,它将返回他们欢迎
//欢迎在下面的会话值中查找 NEWUSER = yes
如果是这样
//scr 现在有 ip 城市/国家/邮政编码,所以它最终确定
通过添加用户 ip country/city/ip 作为他们的注册来添加用户
// 如果不是新的,他们已经从
此代码已将相关会话值放入更新记录和
退还他们我的账户
//如果这里的认证失败或者他们拒绝分享他们的
电子邮件然后返回登录页面
标识符标识符 = this.verifyResponse(req);
如果(标识符!= null){
resp.sendRedirect(scr+"?act=welcome");
} 别的 {
resp.sendRedirect(scr+"?act=login");
}
}
}
// --- 发出认证请求 ---
公共字符串 authRequest(字符串用户提供字符串,字符串 Ouser,
HttpServletRequest httpReq, HttpServletResponse httpResp) 抛出
IO异常{
尝试 {
// 配置应用程序将在其中的 return_to URL
收到
// 来自 OpenID 提供者的身份验证响应
字符串 returnToUrl = httpReq.getRequestURL().toString();
// --- 转发代理设置(仅在需要时) ---
// ProxyProperties proxyProps = new ProxyProperties();
// proxyProps.setProxyName("proxy.example.com");
// proxyProps.setProxyPort(8080);
// HttpClientFactory.setProxyProperties(proxyProps);
// 对用户提供的标识符执行发现
//修改 - 从会话中查找经理值
经理=(消费者经理)
httpReq.getSession().getAttribute("open_id_consumer_manager");
列出发现 = manager.discover(userSuppiedString);
// 尝试与 OpenID 提供者关联
// 并检索一个服务端点进行身份验证
DiscoveryInformation 发现 =
manager.associate(发现);
// 将发现信息存储在用户的会话中
httpReq.getSession().setAttribute("openid-disc", found);
// 获取要发送到 OpenID 的 AuthRequest 消息
提供者
AuthRequest authReq = manager.authenticate(发现,
returnToUrl);
FetchRequest fetch = FetchRequest.createFetchRequest();
如果(用户提供字符串.startsWith(GOOGLE_ENDPOINT)){
fetch.addAttribute("email", "http://axschema.org/
联系方式/电子邮件", true);
fetch.addAttribute("firstName", "http://axschema.org/
namePerson/first", true);
fetch.addAttribute("lastName", "http://axschema.org/
namePerson/last", true);
} else if (userSuppliedString.startsWith(YAHOO_ENDPOINT)) {
fetch.addAttribute("email", "http://axschema.org/
联系方式/电子邮件", true);
fetch.addAttribute("全名", "http://axschema.org/
namePerson", true);
} 别的 {
// 适用于 myOpenID
fetch.addAttribute("全名", "http://
schema.openid.net/namePerson", true);
fetch.addAttribute("email", "http://schema.openid.net/
联系方式/电子邮件", true);
}
httpReq.getSession().setAttribute("Ouser",Ouser);
// 将扩展附加到身份验证请求
authReq.addExtension(fetch);
httpResp.sendRedirect(authReq.getDestinationUrl(true));
} 捕捉(OpenIDException e){
// 向用户显示错误
}
返回空值;
}
// --- 处理认证响应 ---
公共标识符 verifyResponse(HttpServletRequest httpReq) {
尝试 {
// 从认证响应中提取参数
//(来自 OpenID 提供者的 HTTP 请求)
ParameterList 响应 = 新
参数列表(httpReq.getParameterMap());
// 检索之前存储的发现信息
DiscoveryInformation 发现 = (DiscoveryInformation)
httpReq.getSession().getAttribute("openid-disc");
// 从 HTTP 请求中提取接收 URL
StringBuffer 接收URL = httpReq.getRequestURL();
字符串查询字符串 = httpReq.getQueryString();
if (queryString != null && queryString.length() > 0)
接收URL.append("?").append(httpReq.getQueryString());
// 验证响应;ConsumerManager 需要相同
//(静态)用于放置认证请求的实例
//修改 - 在运行验证之前查找会话值
结果
经理=(消费者经理)
httpReq.getSession().getAttribute("open_id_consumer_manager");
验证结果验证 =
manager.verify(receivingURL.toString(), response, found);
// 检查验证结果并提取已验证的
// 标识符
已验证标识符 = verify.getVerifiedId();
字符串 id=verified.getIdentifier();
如果(已验证!= null){
AuthSuccess authSuccess = (AuthSuccess)
验证.getAuthResponse();
如果(authSuccess.hasExtension(AxMessage.OPENID_NS_AX)){
FetchResponse fetchResp = (FetchResponse)
authSuccess.getExtension(AxMessage.OPENID_NS_AX);
列出电子邮件 =
fetchResp.getAttributeValues("email");
String email = (String) emails.get(0);
///////////////////////////////////////// //////////////////////////
//每个人需要实现的自定义位
与他们的应用程序交互:
//验证用户,发送邮件验证是否
用户存在于本地系统上
//如果是{
//
httpReq.getSession().setAttribute("USERNAME",usern);
httpReq.getSession().setAttribute("LOGGEDIN", "on");
//}别的{
字符串名字 =
fetchResp.getAttributeValue("firstName");
字符串姓氏 =
fetchResp.getAttributeValue("lastName");
细绳
全名=fetchResp.getAttributeValue("全名");
如果(全名==空)
{全名="";}
如果(名字==空)
{名字="";}
if (lastName==null) { lastName="";}
if (!fullname.equals("")) {
if (fullname.indexOf(",")>-1)
{
firstName=fullname.substring(0,fullname.indexOf(","));
lastName=fullname.substring(fullname.indexOf(","),fullname.length());
}else if (fullname.indexOf("
")>-1){
firstName=fullname.substring(0,fullname.indexOf(" "));
lastName=fullname.substring(fullname.indexOf(" "),fullname.length());
}
}
//这是返回的用户名
从要求用户名的各种服务中 - 它返回为
openid_username
//当使用openid-selector时,它使用
openid_identifier 和 openid_username - 这就是这个程序现在的内容
寻找
细绳
ouser=(String)httpReq.getSession().getValue("Ouser");
if (user==null) {user="";}
//Adduser -- 传递电子邮件地址和
用户
//在 Adduser 类中 - 如果用户为空
将电子邮件从 0 拆分为 substring.indexOf("@")
// 生成一个随机数 - 查找
当前用户 - 如果存在添加随机数到结束
//并添加带有电子邮件和新用户的用户
用户名
//返回新用户并登录
像上面一样。
httpReq.getSession().setAttribute("NEWUSER","YES");
//
httpReq.getSession().setAttribute("USERNAME",usern);
httpReq.getSession().setAttribute("LOGGEDIN", "on");
//}
退货验证;// 成功
}
}
} 捕捉(OpenIDException e){
// 向用户显示错误
}
返回空值;
}