我在 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){ // 向用户显示错误 } 返回空值; }