Issues (124)

src/Model/Comment/SecurityToken.php (1 issue)

1
<?php
2
3
namespace SilverStripe\Comments\Model\Comment;
4
5
use SilverStripe\Control\Controller;
6
use SilverStripe\Security\Member;
7
use SilverStripe\Security\RandomGenerator;
8
9
/**
10
 * Provides the ability to generate cryptographically secure tokens for comment moderation
11
 */
12
class SecurityToken
13
{
14
    /**
15
     * @var string
16
     */
17
    private $secret = null;
18
19
    /**
20
     * @param Comment $comment Comment to generate this token for
21
     */
22
    public function __construct($comment)
23
    {
24
        if (!$comment->SecretToken) {
25
            $comment->SecretToken = $this->generate();
26
            $comment->write();
27
        }
28
        $this->secret = $comment->SecretToken;
29
    }
30
31
    /**
32
     * Generate the token for the given salt and current secret
33
     *
34
     * @param string $salt
35
     *
36
     * @return string
37
     */
38
    protected function getToken($salt)
39
    {
40
        return hash_pbkdf2('sha256', $this->secret, $salt, 1000, 30);
41
    }
42
43
    /**
44
     * Get the member-specific salt.
45
     *
46
     * The reason for making the salt specific to a user is that it cannot be "passed in" via a
47
     * querystring, requiring the same user to be present at both the link generation and the
48
     * controller action.
49
     *
50
     * @param string $salt   Single use salt
51
     * @param Member $member Member object
52
     *
53
     * @return string Generated salt specific to this member
54
     */
55
    protected function memberSalt($salt, $member)
56
    {
57
        // Fallback to salting with ID in case the member has not one set
58
        return $salt . ($member->Salt ?: $member->ID);
59
    }
60
61
    /**
62
     * @param string $url    Comment action URL
63
     * @param Member $member Member to restrict access to this action to
64
     *
65
     * @return string
66
     */
67
    public function addToUrl($url, $member)
68
    {
69
        $salt = $this->generate(15); // New random salt; Will be passed into url
70
        // Generate salt specific to this member
71
        $memberSalt = $this->memberSalt($salt, $member);
72
        $token = $this->getToken($memberSalt);
73
        return Controller::join_links(
74
            $url,
75
            sprintf(
76
                '?t=%s&s=%s',
77
                urlencode($token),
78
                urlencode($salt)
79
            )
80
        );
81
    }
82
83
    /**
84
     * @param SS_HTTPRequest $request
85
     *
86
     * @return boolean
87
     */
88
    public function checkRequest($request)
89
    {
90
        $member = Member::currentUser();
0 ignored issues
show
Deprecated Code introduced by
The function SilverStripe\Security\Member::currentUser() has been deprecated: 5.0.0 use Security::getCurrentUser() ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

90
        $member = /** @scrutinizer ignore-deprecated */ Member::currentUser();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
91
        if (!$member) {
92
            return false;
93
        }
94
95
        $salt = $request->getVar('s');
96
        $memberSalt = $this->memberSalt($salt, $member);
97
        $token = $this->getToken($memberSalt);
98
99
        // Ensure tokens match
100
        return $token === $request->getVar('t');
101
    }
102
103
104
    /**
105
     * Generates new random key
106
     *
107
     * @param integer $length
108
     *
109
     * @return string
110
     */
111
    protected function generate($length = null)
112
    {
113
        $generator = new RandomGenerator();
114
        $result = $generator->randomToken('sha256');
115
        if ($length !== null) {
116
            return substr($result, 0, $length);
117
        }
118
        return $result;
119
    }
120
}
121