Я создал одностраничное приложение, которое требует username
и password
для аутентификации пользователей.Каждая учетная запись в системе создается администраторами.Пользователь не может щелкнуть ссылку и создать учетную запись.После исследования и поиска лучшего решения первое, что я изменил, было то, как пользователь может восстановить свой пароль.Вот краткая схема того, как работает эта логика.Пользователь сначала должен нажать на ссылку Forgot Password
, ввести свой адрес электронной почты и отправить форму.Они увидят сообщение:
An email has been sent to example@gmail.com with further instructions.
Функция, которая будет выполнять этот процесс, выглядит следующим образом:
cfstoredproc( procedure="CheckEmail", datasource=dsn ) {
cfprocparam( maxlength=80, null=!len(trim(arguments.email)), cfsqltype="cf_sql_varchar", dbvarname="@Email", value=trim(arguments.email) );
cfprocresult( name="EmailResult" );
}
if( EmailResult.recordCount EQ 1) {
// Generate new token
local.newToken = createUUID();
// Build URL with token parameter and add hashed value
local.theUrl = "https://example.com/Reset.cfm?token=" & local.newToken;
// Set expiration time (30 minutes)
local.Expires = DateAdd("n", 30, now());
cfstoredproc( procedure="SaveToken", datasource=dsn ) {
cfprocparam( maxlength=80, null=!len(trim(arguments.email)), cfsqltype="cf_sql_varchar", dbvarname="@Email", value=trim(arguments.email) );
cfprocparam( maxlength=35, null=!len(trim(local.newToken)), cfsqltype="cf_sql_varchar", dbvarname="@Token", value=trim(local.newToken) );
cfprocparam( null=!len(trim(local.Expires)), cfsqltype="cf_sql_timestamp", dbvarname="@Expires", value=trim(local.Expires) );
cfprocresult( name="TokenResult" );
}
if ( len(TokenResult.RecID) ) {
savecontent variable="mailBody"{
writeOutput('<br>Here is your password reset link: <a href="' & theUrl & '">Click here</a> as soon as possible and change your password.<br>' );
}
local.mail = new mail();
// Set it's properties
local.mail.setSubject("Example Application");
local.mail.setTo(arguments.email);
local.mail.setFrom("noreply@example.com");
local.mail.setType("html");
// Send the email
local.mail.send(body = mailBody);
local.fnResults = {status : "200", message : "An email has been sent to <b>" & arguments.email & "</b> with further instructions."};
} else {
local.fnResults = {status : "400", message : "Error! Something went wrong."};
}
}else{
savecontent variable="mailBody"{
writeOutput('<br>We recieved a password reset request. The email you have provided does not exist in our system.<br>');
}
local.mail = new mail();
// Set it's properties
local.mail.setSubject("Example Application");
local.mail.setTo(arguments.email);
local.mail.setFrom("noreply@example.com");
local.mail.setType("html");
// Send the email
local.mail.send(body = mailBody);
local.fnResults = {status : "200", message : "An email has been sent to <b>" & arguments.email & "</b> with further instructions."};
}
Тогда следующим шагом будет, если электронная почта существует и пользовательнажимая на ссылку, я либо покажу форму, где они могут ввести новый пароль, либо они увидят сообщение This link has expired or does not exist anymore.
.Вот пример страницы Reset.cfm
:
if (structKeyExists(url,"token") && isValid("uuid", url.token) && len(trim(url.token)) == 35){
cfstoredproc( procedure="CheckToken", datasource=dsn ) {
cfprocparam( maxlength=35, null=!len(trim(url.token)), cfsqltype="cf_sql_varchar", dbvarname="@Token", value=trim(url.token) );
cfprocresult( name="TokenResult" );
}
if( TokenResult.recordCount == 1 ){ //If token is valid (not expired) show the form.
<form name="frmRecovery" id="frmRecovery" autocomplete="off">
<input type="hidden" name="token" value="<cfoutput>#url.token#</cfoutput>">
<div class="form-group">
<div class="alert alert-info"><strong>Info!</strong> After saving your changes, you will be taken back to the login screen. Log into the system with the account credentials you have just saved.</div>
</div>
<div class="form-group">
<label class="control-label" for="password"><span class="label label-primary">Password</span></label>
<input type="password" class="form-control" name="frmRecovery_password" id="frmRecovery_password" placeholder="Enter Password" maxlength="64" required>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
<div class="form-group">
<div class="alert message-submit"></div>
</div>
</form>
}else{
<div class="alert alert-warning">
<strong>Warrning!</strong> This link has expired or does not exist anymore! </div>
}
}
Если пользователь будет перенаправлен на форму для ввода пароля, я сохраню новый пароль и удалю токен.Следующим шагом является направление их на страницу входа, и они могут ввести учетные данные и войти в систему.Итак, мой вопрос: могу ли я использовать подобный подход, когда администратор создает новую учетную запись?администратор должен ввести first
, last name
, username
и т. д. Затем нажмите кнопку Send Email
, которая перешлет username
и временную ссылку, где новый пользователь сможет ввести свой пароль и войти в приложение.Логика, которая используется ранее, заключается в создании временного пароля, пользователь входит в систему и затем должен сбросить пароль.Мне интересно, если решение, которое я предложил wold, имеет какие-либо риски для безопасности или так же хорошо, как решение с временным паролем?