📄 server.php
字号:
/** * Create a new signatory using a given store. */ function Auth_OpenID_Signatory(&$store) { // assert store is not None $this->store =& $store; } /** * Verify, using a given association handle, a signature with * signed key-value pairs from an HTTP request. */ function verify($assoc_handle, $message) { $assoc = $this->getAssociation($assoc_handle, true); if (!$assoc) { // oidutil.log("failed to get assoc with handle %r to verify sig %r" // % (assoc_handle, sig)) return false; } return $assoc->checkMessageSignature($message); } /** * Given a response, sign the fields in the response's 'signed' * list, and insert the signature into the response. */ function sign($response) { $signed_response = $response; $assoc_handle = $response->request->assoc_handle; if ($assoc_handle) { // normal mode $assoc = $this->getAssociation($assoc_handle, false, false); if (!$assoc || ($assoc->getExpiresIn() <= 0)) { // fall back to dumb mode $signed_response->fields->setArg(Auth_OpenID_OPENID_NS, 'invalidate_handle', $assoc_handle); $assoc_type = ($assoc ? $assoc->assoc_type : 'HMAC-SHA1'); if ($assoc && ($assoc->getExpiresIn() <= 0)) { $this->invalidate($assoc_handle, false); } $assoc = $this->createAssociation(true, $assoc_type); } } else { // dumb mode. $assoc = $this->createAssociation(true); } $signed_response->fields = $assoc->signMessage( $signed_response->fields); return $signed_response; } /** * Make a new association. */ function createAssociation($dumb = true, $assoc_type = 'HMAC-SHA1') { $secret = Auth_OpenID_CryptUtil::getBytes( Auth_OpenID_getSecretSize($assoc_type)); $uniq = base64_encode(Auth_OpenID_CryptUtil::getBytes(4)); $handle = sprintf('{%s}{%x}{%s}', $assoc_type, intval(time()), $uniq); $assoc = Auth_OpenID_Association::fromExpiresIn( $this->SECRET_LIFETIME, $handle, $secret, $assoc_type); if ($dumb) { $key = $this->dumb_key; } else { $key = $this->normal_key; } $this->store->storeAssociation($key, $assoc); return $assoc; } /** * Given an association handle, get the association from the * store, or return a ServerError or null if something goes wrong. */ function getAssociation($assoc_handle, $dumb, $check_expiration=true) { if ($assoc_handle === null) { return new Auth_OpenID_ServerError(null, "assoc_handle must not be null"); } if ($dumb) { $key = $this->dumb_key; } else { $key = $this->normal_key; } $assoc = $this->store->getAssociation($key, $assoc_handle); if (($assoc !== null) && ($assoc->getExpiresIn() <= 0)) { if ($check_expiration) { $this->store->removeAssociation($key, $assoc_handle); $assoc = null; } } return $assoc; } /** * Invalidate a given association handle. */ function invalidate($assoc_handle, $dumb) { if ($dumb) { $key = $this->dumb_key; } else { $key = $this->normal_key; } $this->store->removeAssociation($key, $assoc_handle); }}/** * Encode an {@link Auth_OpenID_ServerResponse} to an * {@link Auth_OpenID_WebResponse}. * * @package OpenID */class Auth_OpenID_Encoder { var $responseFactory = 'Auth_OpenID_WebResponse'; /** * Encode an {@link Auth_OpenID_ServerResponse} and return an * {@link Auth_OpenID_WebResponse}. */ function encode(&$response) { $cls = $this->responseFactory; $encode_as = $response->whichEncoding(); if ($encode_as == Auth_OpenID_ENCODE_KVFORM) { $wr = new $cls(null, null, $response->encodeToKVForm()); if (is_a($response, 'Auth_OpenID_ServerError')) { $wr->code = AUTH_OPENID_HTTP_ERROR; } } else if ($encode_as == Auth_OpenID_ENCODE_URL) { $location = $response->encodeToURL(); $wr = new $cls(AUTH_OPENID_HTTP_REDIRECT, array('location' => $location)); } else if ($encode_as == Auth_OpenID_ENCODE_HTML_FORM) { $wr = new $cls(AUTH_OPENID_HTTP_OK, array(), $response->toFormMarkup()); } else { return new Auth_OpenID_EncodingError($response); } return $wr; }}/** * An encoder which also takes care of signing fields when required. * * @package OpenID */class Auth_OpenID_SigningEncoder extends Auth_OpenID_Encoder { function Auth_OpenID_SigningEncoder(&$signatory) { $this->signatory =& $signatory; } /** * Sign an {@link Auth_OpenID_ServerResponse} and return an * {@link Auth_OpenID_WebResponse}. */ function encode(&$response) { // the isinstance is a bit of a kludge... it means there isn't // really an adapter to make the interfaces quite match. if (!is_a($response, 'Auth_OpenID_ServerError') && $response->needsSigning()) { if (!$this->signatory) { return new Auth_OpenID_ServerError(null, "Must have a store to sign request"); } if ($response->fields->hasKey(Auth_OpenID_OPENID_NS, 'sig')) { return new Auth_OpenID_AlreadySigned($response); } $response = $this->signatory->sign($response); } return parent::encode($response); }}/** * Decode an incoming query into an Auth_OpenID_Request. * * @package OpenID */class Auth_OpenID_Decoder { function Auth_OpenID_Decoder(&$server) { $this->server =& $server; $this->handlers = array( 'checkid_setup' => 'Auth_OpenID_CheckIDRequest', 'checkid_immediate' => 'Auth_OpenID_CheckIDRequest', 'check_authentication' => 'Auth_OpenID_CheckAuthRequest', 'associate' => 'Auth_OpenID_AssociateRequest' ); } /** * Given an HTTP query in an array (key-value pairs), decode it * into an Auth_OpenID_Request object. */ function decode($query) { if (!$query) { return null; } $message = Auth_OpenID_Message::fromPostArgs($query); $mode = $message->getArg(Auth_OpenID_OPENID_NS, 'mode'); if (!$mode) { return new Auth_OpenID_ServerError($message, "No mode value in message"); } $handlerCls = Auth_OpenID::arrayGet($this->handlers, $mode, $this->defaultDecoder($message)); if (!is_a($handlerCls, 'Auth_OpenID_ServerError')) { return call_user_func_array(array($handlerCls, 'fromMessage'), array($message, $this->server)); } else { return $handlerCls; } } function defaultDecoder($message) { $mode = $message->getArg(Auth_OpenID_OPENID_NS, 'mode'); return new Auth_OpenID_ServerError($message, sprintf("No decoder for mode %s", $mode)); }}/** * An error that indicates an encoding problem occurred. * * @package OpenID */class Auth_OpenID_EncodingError { function Auth_OpenID_EncodingError(&$response) { $this->response =& $response; }}/** * An error that indicates that a response was already signed. * * @package OpenID */class Auth_OpenID_AlreadySigned extends Auth_OpenID_EncodingError { // This response is already signed.}/** * An error that indicates that the given return_to is not under the * given trust_root. * * @package OpenID */class Auth_OpenID_UntrustedReturnURL extends Auth_OpenID_ServerError { function Auth_OpenID_UntrustedReturnURL($message, $return_to, $trust_root) { parent::Auth_OpenID_ServerError($message, "Untrusted return_to URL"); $this->return_to = $return_to; $this->trust_root = $trust_root; } function toString() { return sprintf("return_to %s not under trust_root %s", $this->return_to, $this->trust_root); }}/** * I handle requests for an OpenID server. * * Some types of requests (those which are not checkid requests) may * be handed to my {@link handleRequest} method, and I will take care * of it and return a response. * * For your convenience, I also provide an interface to {@link * Auth_OpenID_Decoder::decode()} and {@link * Auth_OpenID_SigningEncoder::encode()} through my methods {@link * decodeRequest} and {@link encodeResponse}. * * All my state is encapsulated in an {@link Auth_OpenID_OpenIDStore}. * * Example: * * <pre> $oserver = new Auth_OpenID_Server(Auth_OpenID_FileStore($data_path), * "http://example.com/op"); * $request = $oserver->decodeRequest(); * if (in_array($request->mode, array('checkid_immediate', * 'checkid_setup'))) { * if ($app->isAuthorized($request->identity, $request->trust_root)) { * $response = $request->answer(true); * } else if ($request->immediate) { * $response = $request->answer(false); * } else { * $app->showDecidePage($request); * return; * } * } else { * $response = $oserver->handleRequest($request); * } * * $webresponse = $oserver->encode($response);</pre> * * @package OpenID */class Auth_OpenID_Server { function Auth_OpenID_Server(&$store, $op_endpoint=null) { $this->store =& $store; $this->signatory =& new Auth_OpenID_Signatory($this->store); $this->encoder =& new Auth_OpenID_SigningEncoder($this->signatory); $this->decoder =& new Auth_OpenID_Decoder($this); $this->op_endpoint = $op_endpoint; $this->negotiator =& Auth_OpenID_getDefaultNegotiator(); } /** * Handle a request. Given an {@link Auth_OpenID_Request} object, * call the appropriate {@link Auth_OpenID_Server} method to * process the request and generate a response. * * @param Auth_OpenID_Request $request An {@link Auth_OpenID_Request} * returned by {@link Auth_OpenID_Server::decodeRequest()}. * * @return Auth_OpenID_ServerResponse $response A response object * capable of generating a user-agent reply. */ function handleRequest($request) { if (method_exists($this, "openid_" . $request->mode)) { $handler = array($this, "openid_" . $request->mode); return call_user_func($handler, $request); } return null; } /** * The callback for 'check_authentication' messages. */ function openid_check_authentication(&$request) { return $request->answer($this->signatory); } /** * The callback for 'associate' messages. */ function openid_associate(&$request) { $assoc_type = $request->assoc_type; $session_type = $request->session->session_type; if ($this->negotiator->isAllowed($assoc_type, $session_type)) { $assoc = $this->signatory->createAssociation(false, $assoc_type); return $request->answer($assoc); } else { $message = sprintf('Association type %s is not supported with '. 'session type %s', $assoc_type, $session_type); list($preferred_assoc_type, $preferred_session_type) = $this->negotiator->getAllowedType(); return $request->answerUnsupported($message, $preferred_assoc_type, $preferred_session_type); } } /** * Encodes as response in the appropriate format suitable for * sending to the user agent. */ function encodeResponse(&$response) { return $this->encoder->encode($response); } /** * Decodes a query args array into the appropriate * {@link Auth_OpenID_Request} object. */ function decodeRequest($query=null) { if ($query === null) { $query = Auth_OpenID::getQuery(); } return $this->decoder->decode($query); }}?>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -