Nou*_*man 26 php oop login class
开始尝试构建类,我开始将用户注册/登录转换为单个类.想要在走得太远之前停下来寻求反馈.
class UserService
{
private $_email;
private $_password;
public function login($email, $password)
{
$this->_email = mysql_real_escape_string($email);
$this->_password = mysql_real_escape_string($password);
$user_id = $this->_checkCredentials();
if($user_id){
$_SESSION['user_id'] = $user_id;
return $user_id;
}
return false;
}
protected function _checkCredentials()
{
$query = "SELECT *
FROM users
WHERE email = '$this->_email'";
$result = mysql_query($query);
if(!empty($result)){
$user = mysql_fetch_assoc($result);
$submitted_pass = sha1($user['salt'] . $this->_password);
if($submitted_pass == $user['password']){
return $user['id'];
}
}
return false;
}
}
Run Code Online (Sandbox Code Playgroud)
我与课程有关的一个问题是:我应该像这样构建它:
$User = new UserService();
$User->login($_POST['email'], $_POST['password']);
Run Code Online (Sandbox Code Playgroud)
login方法自动调用_checkCredentials方法的位置.或者它应该像:
$User = new UserService();
$UserId = $User->checkCredentials($_POST['email'], $_POST['password']);
$User->login($UserId);
Run Code Online (Sandbox Code Playgroud)
除此之外,我喜欢一些关于如何重组这个的提示,请指出我做错的任何事情!
多谢你们
net*_*der 39
我认为你的主要想法是将用户处理(会话)与数据库查询分开,这在我看来是一件好事.
但是,实际实现并非如此,因为login
将数据转义为要发送到数据库的数据,即使该方法的其余部分与数据库没有任何关系也是如此.并不是说您的数据库查询依赖于全局资源来工作.虽然我在这,但我也建议你使用PDO.
此外,你的属性$_email
和$_password
在私人范围,但要由一个受保护的方法访问.这可能会导致问题.属性和方法应具有相同的可见性.
现在,我可以看到您UserService
需要三件事:数据库处理程序,电子邮件和密码.将它放在构造函数中是有意义的.
我是这样做的:
class UserService
{
protected $_email; // using protected so they can be accessed
protected $_password; // and overidden if necessary
protected $_db; // stores the database handler
protected $_user; // stores the user data
public function __construct(PDO $db, $email, $password)
{
$this->_db = $db;
$this->_email = $email;
$this->_password = $password;
}
public function login()
{
$user = $this->_checkCredentials();
if ($user) {
$this->_user = $user; // store it so it can be accessed later
$_SESSION['user_id'] = $user['id'];
return $user['id'];
}
return false;
}
protected function _checkCredentials()
{
$stmt = $this->_db->prepare('SELECT * FROM users WHERE email=?');
$stmt->execute(array($this->email));
if ($stmt->rowCount() > 0) {
$user = $stmt->fetch(PDO::FETCH_ASSOC);
$submitted_pass = sha1($user['salt'] . $this->_password);
if ($submitted_pass == $user['password']) {
return $user;
}
}
return false;
}
public function getUser()
{
return $this->_user;
}
}
Run Code Online (Sandbox Code Playgroud)
然后使用它:
$pdo = new PDO('mysql:dbname=mydb', 'myuser', 'mypass');
$userService = new UserService($pdo, $_POST['email'], $_POST['password']);
if ($user_id = $userService->login()) {
echo 'Logged it as user id: '.$user_id;
$userData = $userService->getUser();
// do stuff
} else {
echo 'Invalid login';
}
Run Code Online (Sandbox Code Playgroud)
Alf*_*red 14
我之前已经在stackoverflow上说了很多,但我认为你做错了就是你再次尝试创建一个登录系统(甚至Jeff Atwood也同意我的意见),这可能是不安全的.仅举几个可能出错的事情:
然后,我们还没有在您的服务器上创建另一个帐户的烦恼.你可以而且应该避免这种麻烦,使用一种免费提供的替代品,这些替代品已经过专家测试的安全漏洞:
因此,您可以安全地再次设计另一个登录系统,而不是使用例如非常简单的lightopenid库,并允许用户使用Google帐户登录.下面的代码段是您运行它所需的唯一代码:
<?php
# Logging in with Google accounts requires setting special identity, so this example shows how to do it.
require 'openid.php';
try {
$openid = new LightOpenID;
if(!$openid->mode) {
if(isset($_GET['login'])) {
$openid->identity = 'https://www.google.com/accounts/o8/id';
header('Location: ' . $openid->authUrl());
}
?>
<form action="?login" method="post">
<button>Login with Google</button>
</form>
<?php
} elseif($openid->mode == 'cancel') {
echo 'User has canceled authentication!';
} else {
echo 'User ' . ($openid->validate() ? $openid->identity . ' has ' : 'has not ') . 'logged in.';
}
} catch(ErrorException $e) {
echo $e->getMessage();
}
Run Code Online (Sandbox Code Playgroud)