|
最近公司换了yaf框架,突然对用c实现php拓展感兴趣了,如果一个功能已经很稳定很成熟而且用的地方很多,那么我们就可以尝试用拓展实现(不一定每种情况都可以写成拓展),写成拓展后就不用每次用都包含一下,工具类直接随php启动加载进内存里。
我这次是把用户会话加密类写成了php的拓展,用户类是基于des加密的,主要实现了,
- isLogin //判断是否登录
- setLogin //就是种个加密的cookie
- getUid
- getUsername
我给这个项目起名slime(史莱姆),勇者斗恶龙里的小怪,黏黏的。。。。。。
ok,先来看下php的实现,因为我们是php -> c,所以先看下php的实现,其实就是很普通用户类
1 <?php
2 class Session_DES
3 {
4 var $key;
5 var $iv; //偏移量
6
7 function Session_DES( $key="AAAAAAAA", $iv="BBBBBBBB") {
8 //key长度8例如:1234abcd
9 $this->key = $key;
10 if( $iv == "" ) {
11 $this->iv = $key; //默认以$key 作为 iv
12 } else {
13 $this->iv = $iv; //mcrypt_create_iv ( mcrypt_get_block_size (MCRYPT_DES, MCRYPT_MODE_CBC), MCRYPT_DEV_RANDOM );
14 }
15 }
16
17 function encrypt($str) {
18 //加密,返回大写十六进制字符串
19 $size = mcrypt_get_block_size ( MCRYPT_DES, MCRYPT_MODE_CBC );
20 $str = $this->pkcs5Pad ( $str, $size );
21 return strtoupper( bin2hex( mcrypt_cbc(MCRYPT_DES, $this->key, $str, MCRYPT_ENCRYPT, $this->iv ) ) );
22 }
23
24 function decrypt($str) {
25 //解密
26 $strBin = $this->hex2bin( strtolower( $str ) );
27 $str = mcrypt_cbc( MCRYPT_DES, $this->key, $strBin, MCRYPT_DECRYPT, $this->iv );
28 $str = $this->pkcs5Unpad( $str );
29 return $str;
30 }
31
32 function hex2bin($hexData) {
33 $binData = "";
34 for($i = 0; $i < strlen ( $hexData ); $i += 2) {
35 $binData .= chr ( hexdec ( substr ( $hexData, $i, 2 ) ) );
36 }
37 return $binData;
38 }
39
40 function pkcs5Pad($text, $blocksize) {
41 $pad = $blocksize - (strlen ( $text ) % $blocksize);
42 return $text . str_repeat ( chr ( $pad ), $pad );
43 }
44
45 function pkcs5Unpad($text) {
46 $pad = ord ( $text {strlen ( $text ) - 1} );
47 if ($pad > strlen ( $text ))
48 return false;
49 if (strspn ( $text, chr ( $pad ), strlen ( $text ) - $pad ) != $pad)
50 return false;
51 return substr ( $text, 0, - 1 * $pad );
52 }
53 }
再来看Session_User
1 <?php
2 define ('BACK_AUTH_NAME','xxxx'); //用到的cookie名
3 class Session_User {
4 static $obj;
5 private $uid;
6 private $username;
7 private $chineseName;
8 public $auth_name = BACK_AUTH_NAME;
9 private $login_url = null;
10 public $domain = null;
11
12 private function __construct($login_url = null, $domain = null){
13 $host = $_SERVER["HTTP_HOST"];
14 if (!$login_url) {
15 $this->login_url = "http://{$host}/login";
16 }
17 else {
18 $this->login_url = $login_url;
19 }
20
21 if (!$domain) {
22 $domain = $_SERVER["SERVER_NAME"];
23 $this->domain = $domain;
24 }
25
26 if (empty ( $_COOKIE [$this->auth_name] )) {
27 return;
28 }
29
30 list ( $uid, $username, $ua, $tm, $chineseName ) = @$this->decodeAuth ($_COOKIE [$this->auth_name]);
31
32
33 //ua检验
34 if (empty ( $uid ) || $ua !== md5($_SERVER ['HTTP_USER_AGENT'])) {
35 return;
36 }
37
38 //TODO:过期时间检验
39
40 $this->uid = $uid;
41 $this->username = $username;
42 $this->chineseName = $chineseName;
43 }
44
45 static public function instance($login_url = null, $domain = null){
46 if(self::$obj)
47 return self::$obj;
48 else{
49 self::$obj = new Session_User($login_url, $domain);
50 }
51 return self::$obj;
52 }
53
54
55 /**
56 * 用户是否登陆
57 * */
58 public function isLogin(){
59 if(! empty($this->uid))
60 return true;
61 else
62 return false;
63 }
64 /**
65 *
66 * 跳转到登录页面
67 * @param unknown_type $forward
68 * @param unknown_type $exit
69 */
70 public function requireLogin($forward = '', $exit = true){
71 if(! $this->isLogin()){
72 if($forward === null)
73 {
74 header("location: " . $this->login_url);
75
76 }
77 else
78 {
79 if(empty($forward))
80 {
81 $forward = 'http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];
82 }
83 $forward = urlencode($forward);
84 header("location: ". $this->login_url . "?forward=$forward");
85 }
86 if($exit)
87 exit;
88 }
89 }
90 /**
91 *
92 *设置登录状态
93 * @param unknown_type $uid
94 * @param unknown_type $username
95 * @param unknown_type $ua
96 * @param unknown_type $outtime
97 */
98
99 public function setLogin($uid, $username, $ua = null,$outtime = null, $chineseName = null){
100 if(empty($ua)){
101 $ua = $_SERVER['HTTP_USER_AGENT'];
102 }
103
104 $str = $this->encodeAuth($uid, $username, $ua, $chineseName);
105 setcookie($this->auth_name,urlencode($str),$outtime,'/',$this->domain);
106 }
107 /**
108 * 用户退出
109 */
110 public function setLogout(){
111 setcookie($this->auth_name,'',-1,'/',$this->domain);
112 }
113
114 public function __get($key){
115 if('uid' == $key){
116 return $this->uid;
117 }elseif ('username' == $key) {
118 return $this->username;
119 }elseif ('chineseName' == $key) {
120 return $this->chineseName;
121 }
122 return ;
123 }
124
125 public function getUid(){
126 return $this->uid;
127 }
128
129 public function getUserName(){
130 return $this->username;
131 }
132
133 public function getChineseName(){
134 return $this->chineseName;
135 }
136
137 /**
138 * 生成加密的登陆cookie
139 */
140 private function encodeAuth($uid,$username,$ua,$chineseName=null){
141 $tm = time();
142 $ua = md5($ua);
143 $info = "$uid\t$username\t$ua\t$tm\t$chineseName";
144 $des = new Session_DES();
145 $str = $des->encrypt($info);
146 return $str;
147 }
148
149 /**
150 * 解析加密cookie
151 */
152 private function decodeAuth($str){
153 $des = new Session_DES();
154 $info = explode("\t",@$des->decrypt($str));
155 if(is_array($info)){
156 return $info;
157 }else{
158 return array();
159 }
160 }
161
162 public function auth($controller,$action)
163 {
164 if(!in_array($controller,$conArr)){
165 return false;
166 }
167 if(!in_array($action,$actArr)){
168 return false;
169 }
170 return true;
171 }
172 }
View Code 结合上面两段代码,分离出来其实得到的会话类(常常做的就是把一样的的跟不一样的分离出来),只需要3个变量两个是des用到的iv偏移量,key加密秘钥,跟cookie名,然后我们就可以写我们的拓展了,其中踩到了很多坑,一些makefile,config.w4等小语法,lib依赖,总之还是学到了很多
代码地址:https://github.com/lietdai/ldclass
|
|