1: <?php
2:
3: /**
4: * Wei Framework
5: *
6: * @copyright Copyright (c) 2008-2015 Twin Huang
7: * @license http://opensource.org/licenses/mit-license.php MIT License
8: */
9:
10: namespace Wei;
11:
12: /**
13: * Generate a URL with signature
14: *
15: * @property \Wei\Request $request
16: */
17: class SafeUrl extends Base
18: {
19: /**
20: * The token to generate the signature
21: *
22: * @var string
23: */
24: protected $token = 'wei';
25:
26: /**
27: * The expire seconds of signature
28: *
29: * @var int
30: */
31: protected $expireTime = 60;
32:
33: /**
34: * Generate signature for specified parameter names
35: *
36: * @var array
37: */
38: protected $params = array();
39:
40: /**
41: * Generate a URL with signature, alias of generate method
42: *
43: * @param string $url
44: * @return string
45: */
46: public function __invoke($url)
47: {
48: return $this->generate($url);
49: }
50:
51: /**
52: * Generate a URL with signature
53: *
54: * @param string $url
55: * @return string
56: */
57: public function generate($url)
58: {
59: $time = time();
60: $query = parse_url($url, PHP_URL_QUERY);
61: parse_str($query, $query);
62:
63: $query = $this->filterKeys($query, $this->params);
64: $query['timestamp'] = $time;
65:
66: $signature = $this->generateToken($query);
67:
68: return $url . '×tamp=' . $time . '&signature=' . $signature;
69: }
70:
71: /**
72: * Verify whether the URL signature is OK
73: *
74: * @return bool
75: */
76: public function verify()
77: {
78: // Check if time is expired
79: $time = $this->request->getQuery('timestamp');
80: if ($this->expireTime && time() - $time > $this->expireTime) {
81: return false;
82: }
83:
84: // Remove signature parameters
85: $query = $this->request->getParameterReference('get');
86: $token = $this->request->getQuery('signature');
87: unset($query['signature']);
88:
89: $timestamp = $query['timestamp'];
90:
91: $query = $this->filterKeys($query, $this->params);
92:
93: $query['timestamp'] = $timestamp;
94:
95: return $this->generateToken($query) == $token;
96: }
97:
98: /**
99: * Set parameter names to generate signature
100: *
101: * @param string|array $params
102: * @return $this
103: */
104: public function setParams($params)
105: {
106: $this->params = (array)$params;
107: return $this;
108: }
109:
110: /**
111: * Generate signature by specified array
112: *
113: * @param array $array
114: * @return string
115: */
116: protected function generateToken(array $array)
117: {
118: return md5(implode('|', $array) . $this->token);
119: }
120:
121: /**
122: * Removes array element by keys
123: *
124: * @param string $query
125: * @param array $keys
126: * @return array
127: */
128: protected function filterKeys($query, $keys)
129: {
130: return $keys ? array_intersect_key($query, array_flip((array)$keys)) : $query;
131: }
132: }