Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   [решено] (C++ Builder) Программа аутентификации - проблема вызова диалоговых окон и сохранения (http://forum.oszone.net/showthread.php?t=121991)

Luzuk 05-11-2008 05:49 943289

(C++ Builder) Программа аутентификации - проблема вызова диалоговых окон и сохранения
 
Здравствуйте, еще раз.
Помогите, пожалуйста, написать программу разграничения полномочий пользователей на основе парольной аутентификации.
Программу пишу в C++ Builder 6.

Условия задачи
читать дальше »

1) Программа должна обеспечивать работу в двух режимах: администратора (пользователя с фиксированным именем ADMIN) и обычного пользователя.

2) Администратор может редактировать данные всех пользователей, включая свои. Пользователь может только менять свой пароль.

3) Данные о пользователях должны храниться в файле.

4) Интерфейс с программой должен быть организован на основе меню, и панели управления (желанно).

5) Для реализации указанных в пунктах 2 функций в программе должны использоваться специальные диалоговые формы, позволяющие пользователю (администратору) вводить необходимую информацию.


Большую часть функций программы я уже сделал, осталось реализовать интерфейс и режим доступа пользователь/админ.

С этим есть небольшие проблемы, не могу понять, как из одного диалогового окна вызвать другое, в частности как сделать так, чтобы при щелчке в пункте меню «Смена пароля», открылось окно для смены пароля текущего пользователя (не стандартное, а созданное мной, допустим «Form3»).

И второе, как лучше реализовать сохранение текущей сессии, то есть, чтобы программа помнила под каким пользователем мы в нее зашли.
Я думал, что можно создать глобальную переменную, в которой хранить имя текущего пользователя, только не знаю как можно использовать эту переменную из разных форм.

Delirium 05-11-2008 06:54 943313

пункты 1-5:
http://rsdn.ru - Статьи - безопасность - Класс для работы с паролями. Язык немного отличается (.NET), но принцип должен быть понятен. Я как то использовал данный класс, тоже была авторизация для админа и пользователя с разграничением прав. И вообще полазийте по rsdn, данный форум очень авторитетен в плане программирования.

Цитата:

Цитата Luzuk
не могу понять, как из одного диалогового окна вызвать другое, в частности как сделать так, чтобы при щелчке в пункте меню «Смена пароля» »

Для этого необходимо проделать следующие шаги(пример на C#, главное смысл):
1. Скрытие основной формы (MainFrm.Hide())
2. Отображение Вашей формы ( ChildFrm.ShowDialog() или ChildFrm.ShowModal() )
3. В дочерней форме уже идет реализация того что вам нужно. Должна быть кнопка Выход или крестик закрытия формы.
4. После ChildFrm.ShowDialog() вновь отображаете Вашу основую форму MainFrm.Show()l
Вот примерно так.

При входе в программу запрашиваете имя и пароль. В случае успеха проверяете в своем файле, является ли данная учетка админской. Если да, то, например, можно отображать нужные пункты меню, либо, если это простой пользователь, ненужные ему опции можно сделать Disable.

Luzuk 05-11-2008 07:28 943319

Ну, это все понятно, только дело в том, что я не знаю, как в Билдере сделать окно дочерним, чтобы потом к нему можно было обращаться.
Алгоритм работы программы мне полностью понятен, вот только с реализацией не идет.

К примеру, я могу на действие "нажатие кнопки" поставить Form1->Visible=false;, тогда окно Form1 исчезнет, но это действие можно делать только внутри этой формы, а мне нужно, чтобы что-то подобное я мог сделать из другой формы.

То есть, мне нужно, чтобы при нажатии на кнопку в Form1, открывалась Form2.

Если я в обработчике нажатии кнопки, в Form1, пишу Form2->Visible=true, выдается ошибка, что он не знает что такое Form2. Значит к Form2 нужно как-то по другому обращаться, либо использоваться другое обращение.
Скорей всего для этого нужно использовать функцию какую-нибудь, возможно CreateDialog() или CreateWindowEx(). Только не знаю, что в эту функцию в качестве параметров вводить.

Delirium 05-11-2008 07:59 943325

ну тогда гугл в помощь:
http://wincmd.ru/article/ListSimpleBcb.html
цитата оттуда:
Цитата:

Чтобы создать дочернее окно воспользуемся статической функцией CreateParentedControl класса TWinControl, т.е. в теле функции функция ShowRTF воспользуемся следующим оператором:
fmMain = (TfmMain *)(TWinControl::CreateParentedControl(__classid(TfmMain), ListerWin));
либо сюда
ну или просто вот так

Luzuk 05-11-2008 08:15 943339

Delirium, Спасибо!
а то я ищу ищу... и ничего полезного так и не нашел... Правда искал по другим ключевым полям.

Luzuk 05-11-2008 08:58 943354

Забавно.

Все оказалось гораздо проще. Нужно было всего лишь в Unit1.cpp добавить
Код:

#include "Unit2.h"
Тогда без проблем можно обращаться к Form2.

Подробней
читать дальше »
В проекте есть две формы Form1 и Form2.
Их описание находятся в Unit1.cpp, Unit1.h и в Unit2.cpp, Unit2.h соответственно.
Также еще есть Project1.cpp и Project1.h, в этом файле находиться главная функция WinMain, которая срабатывает первой при запуске программы.
Важно чтобы в Project1.cpp были определенны обе формы
Код:

USEFORM("Unit1.cpp", Form1);
USEFORM("Unit2.cpp", Form2);
//---------------------------------------------------------------------------
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
        try
        {
                Application->Initialize();
                Application->CreateForm(__classid(TForm1), &Form1);
                Application->CreateForm(__classid(TForm2), &Form2);
                Application->Run();
        }
............

Изначально обращаться к формам можно только из них самих. Чтобы это исправить нужно просто в .cpp файл формы 1, из которой мы хотим обращаться к другой форме, включить .h файл формы 2.
Т.е. если мы хотим из Form1 обращаться к Form2, нужно в Unit1.cpp добавить
Код:

#include "Unit2.h"
После этого, в обраточике событий Form1 можно использоваться вызов Form2, к примеру так:
Код:

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  Form2->Visible=true;
}


Delirium 05-11-2008 09:02 943355

Радует, что Вы сами нашли решение своей проблемы, заодно заполнив небольшой пробельчик в знании языка :)
Если вопрос закрыт, отметьте тему решенной ("Настройки темы" вверху страницы - отметить решенной)

Luzuk 05-11-2008 09:41 943381

Delirium, Ну я еще не все сделал, возможно скоро еще вопросы появятся.
Как программа полностью доделаю, отпишусь здесь ;)

Еще не проверял по поводу того, где лучше хранить запись о текущем пользователе.
Я просто создал файл "users.h" с глобальной переменной (char session_user[16]), в которой храниться идентификатор пользователя. Этот файл прикрепил ко всем .cpp файлам проекта (#include "users.h"). Это сработало, хотя вроде бы так делать не очень правильно, у меня сразу вышло предупреждение:
[Linker Warning] Public symbol '_session_user' defined in both module D:\KEEPER\MY PROGS\LOGIN_PASS_0\UNIT1.OBJ and D:\KEEPER\MY PROGS\LOGIN_PASS_0\UNIT2.OBJ

Хотя стоить учесть, что программа носит чисто демонстрационный характер, для демонстрации аутентификации, а также работы с файлами, так что безопасность и эстетика реализации тут не так уж и важна.


PS
Спасибо что подсказал, как можно пометить тему что задача решена, а то я не знал, и об этом модераторов просил :)

Luzuk 05-11-2008 11:02 943451

Нет, не получилось использовать глобальную переменную для обмена информацией между Формами.

Делал так, есть две формы: Form1 и Form2.
Также есть файл "users.h", в котором находиться переменная для хранения имя пользователя.
В Form1 вводим имя пользователя, после чего открываем Form2 и там по этому имени (что мы ввели в Form1) должен происходить его поиск в файле. Но этого не происходит, т.к. Form1 не смог ни чего записать в эту переменную.

ниже привожу краткий листинг этих файлов:
читать дальше »

users.h
Код:

#ifndef usersH
#define usersH

#include<iostream>
#include<fstream>
#include<string.h>
#include<stdlib.h>
#include<windows.h>
//Глобальная переменная для хранения имени пользователя
extern char session_user[16]="";
#endif

Unit1.cpp
Код:

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include "Unit2.h"
#include "users.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
void __fastcall TForm1::Button1Click(TObject *Sender)
{
        //Копируем то что ввели в Edit1 в переменную session_user
        strcpy(session_user,Edit1->Text.c_str());
        Form2->Visible=true;
        Form1->Visible=false;
}

Unit2.cpp
Код:

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#include "Unit2.h"
#include "users.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;
void __fastcall TForm2::Button1Click(TObject *Sender)
{
        //ищем пользователя имя которого указана в session_user
        find_u(session_user); //но ничего не происходит, т.к. session_user пустой
}


Delirium 06-11-2008 01:03 944432

Ну и не парьтесь вы с этими заголовками. Есть 2 варианта.
1. Самый тупой и простой - при вводе имени пользователя сохранять его в пустой текстовый файл. Если файл есть, переписать его. Таким образом, в текстовике всегда будет лежать имя последнего пользователя.
2. Сохранять имя не в файле, а в реестре, создать программно ветку в HKEY_CURRENT_USER\Software и также точно считывать.

Luzuk 06-11-2008 05:34 944546

Ну, я тоже думал об этом, но с этой проблемой я тоже уже разобрался ;)
Все отлично работает. Просто я немного напутал с определением глобальной переменной, давно этим не занимался и забыл как правильно делать.

Решил проблему так:
В основной форме, которая запускается первой и в которой изначально вводится имя пользователя (Unit1.cpp) создал обычную глобальную переменную: char session_user[16];
А в users.h уже определил ее как общую глобальную переменную: extern char session_user[16];. А так как users.h прикрепляется ко всем .cpp файлам проекта, то через него без проблем можно обращаться и к session_user.

Так что вроде бы все решил, одно но, выше описанный способ вызова одной формы из другой оказался не самым удачным, так как окна независимы и свободно перекрывают друг друга, в отличие от вызова дочерних окон, которые всегда высвечиваются поверх родительских.

Ну, это уже не так страшно, может и с этим еще удастся разобраться ;)


Время: 05:21.

Время: 05:21.
© OSzone.net 2001-