Главная > Flex > Модуль авторизации для Flex-приложений (part 2)

Модуль авторизации для Flex-приложений (part 2)

Продолжение по теме: “Модуль авторизации для Flex-приложений”
начало тут

Итак строим Flex-client side

Проект состоит из следующих файлов.
1. index.mxml – главное приложение в котором нам необходима авторизация
2. com/control/maincontrol.as – вся логика главного приложения по обработке событий авторизации
3. com/events/LoginEvent.as – Custom event при помощи которого передаем данные в главное приложение
4. com/view/LoginWindow.mxml – модуль авторизации, построенный на базе TitleWindow
5. com/vo/GALLuserVO.as – value-object класс содержащий все данные пользователя


Логика:
- По нажатию кнопки “cbLogin” создается окно для авторизации
- в LoginWindow по нажатию кнопки “cbSubmit” передаются данные (login/password) в файл login.php
- login.php генерирует различные XML (смотри part1)
- LoginWindow анализирует входящие XML и генерирует alert или объект с данными
- объект с данными передается через CustomEvent главному приложению

Несколько замечаний:

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

Структура проекта

Структура проекта

главный файл
index.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
				layout="absolute">

	<mx:Style>
		Application
			{
		    paddingLeft: 10px;
		    paddingRight: 10px;
		    paddingTop: 10px;
		    paddingBottom: 10px;
		    backgroundGradientColors: #2F3D45, #5B7685;
		    }
	    Alert
	    	{
			backgroundColor:#eeeeee;
			color: #323232;
			borderColor: #cc0000;
			fontWeight:bold;
			borderAlpha: 0.7;
			headerHeight:20;
			themeColor: #848484;
			titleStyleName:alertTitle;
			}
		.alertTitle
		{
		color:#ffffff;
		fontWeight:bold;
		}
	</mx:Style>

	<!-- базовая логика -->
	<mx:Script source="com/control/maincontrol.as"/>

   	<mx:ApplicationControlBar id="appContolBar" dock="true" paddingTop="2" paddingBottom="2"  alpha="1.0">
		<mx:Spacer width="100%" />
		<mx:Button id="cbLogin" label="Login"
			   click="showLoginWindow()"
			   icon="@Embed(source='assets/icons/user.png')"
			   />

	</mx:ApplicationControlBar>

</mx:Application>

и файл базовой логики maincontrol.as

/******************************************************************************
 *  импорт components
 ******************************************************************************/

// import своих компонент
import com.events.LoginEvent;
import com.view.LoginWindow;
import com.vo.GALLuserVO;

// Импорт Flex компонент
import mx.controls.Alert;
import mx.managers.PopUpManager;

/******************************************************************************
 * объявление переменных
 ******************************************************************************/

// переменная содержащая данные пользователя
private var userData:GALLuserVO;

// создание переменных для окон
private var loginWindow:LoginWindow;

/******************************************************************************
 * блок обработки кнопок
 ******************************************************************************/

// перехватчик нажатия кнопки Login
private function showLoginWindow():void{
	// добавляем окно авторизации в главное приложение
	var loginForm:LoginWindow = LoginWindow(PopUpManager.createPopUp(this, LoginWindow, false));
		loginForm.setStyle("borderAlpha", 0.8);

	// добавляем прослушку окна Login
	loginForm.addEventListener("user", loginFormHandler);
	}

// перехватчик события по авторизации
private function loginFormHandler(event:LoginEvent):void{
	// получаем данные из евента
	userData = event.userVO;

	//выводим на экран данные о пользователе
	var UserMessage:String = event.userVO.usersUsername;
		UserMessage += "\n\n" + event.userVO.usersFirstname;
		UserMessage += "\n\n" + event.userVO.usersLastname;
		UserMessage += "\n\n" + event.userVO.usersDepartment;
		UserMessage += "\n\n" + event.userVO.usersAppointment;
		UserMessage += "\n\n" + event.userVO.usersEmail;
		UserMessage += "\n\n" + event.userVO.usersPermission;

	Alert.show(UserMessage, "Данные о пользователе");

	// в принципе здесь размещаем переход на действие которое мы планируем...
	// do it something with userdata

	// я в зависимости от содержания usersPermission открывал некоторые кнопки

	}
/******************************************************************************
 * конец
 ******************************************************************************/

В итоге получим примерно такую картинку:
MainWindow

Создаем новый MXML component
LoginWindow.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml"
	horizontalCenter="0" verticalCenter="0"
	layout="absolute"
	width="200" height="200"
	title="Авторизация"
	status="Close"
	creationComplete="init();"
	showCloseButton="true"
	close="closeWin()"
	>

	<!-- обязательный тег с метаданными где мы присваиваем имя нашему Custom Event -->
	<mx:Metadata>
		[Event(name="user", type="com.events.LoginEvent")]
	</mx:Metadata>

	<mx:Script>
		<![CDATA[
			import com.events.LoginEvent;
			import com.vo.GALLuserVO;
			import mx.controls.Alert;
			import mx.managers.PopUpManager;
			import mx.rpc.events.FaultEvent;
			import mx.rpc.events.ResultEvent;
			import mx.rpc.http.HTTPService;

			private var tempUserName:String;

			private var myData:Object;

			private var UserData:GALLuserVO = new GALLuserVO();
			private var gateway:HTTPService = new HTTPService();

			private function init():void{

				PopUpManager.centerPopUp(this);
				username.setFocus();

			}

			private function closeWin():void{
				// сброс полей
				username.text = "";
				password.text = "";
				// убираем с экрана
				PopUpManager.removePopUp(this);
			}

			private function loginSubmitHanler():void {
				// объект содержащий поля с логином и паролем для отсылки
				var UserLoginObj:Object;
				UserLoginObj = {"username":username.text, "password":password.text};
				// отправка на проверку имени и пароля
				sendUser(UserLoginObj);
			}

			private function sendUser(setUser:Object):void
			{
				// сохраняем имя
				tempUserName = setUser.username;

				// заносим в запрос данные и отправляем на сервер
				gateway.url = "assets/php/login.php";
				gateway.method = "POST";
				gateway.useProxy = false;
				gateway.showBusyCursor = true;
				gateway.addEventListener(ResultEvent.RESULT, checkUser);
				gateway.addEventListener(FaultEvent.FAULT, faultHandler);
				gateway.request = setUser;
				gateway.send();
			}

			private function checkUser(event:ResultEvent):void
			{
				// загружаем данные из XML
				myData = event.result.data;

				// проверка ошибок соединения
				if (myData.error == "yes")
					{
						// передаем в алерт описание ошибки
						mySQLAlert(myData.error_num, myData.error_desc);
					}
					else
					{
						// успешное соединение - пользователь есть в базе
						if(myData.loginsuccess == "yes")
						{
							// наполнение объекта данными
							UserData.usersUsername = tempUserName;
							UserData.usersFirstname = myData.Ufirstname
							UserData.usersLastname = myData.Ulastname;
							UserData.usersEmail = myData.Uemail;
							UserData.usersDepartment = myData.Udepartment;
							UserData.usersAppointment = myData.Uappointment;
							UserData.usersPermission = myData.Upermission;

							// сброс полей
							username.text = "";
							password.text = "";

							// отправка данных через евент в главное приложение
							var e:LoginEvent = new LoginEvent("user", UserData);
							dispatchEvent(e);

							// закрываем окно
							closeWin();
						}
						else
						// успешное соединение - но пользователя нет в базе
						{
							// сброс полей
							username.text = "";
							password.text = "";
							Alert.show("Invalid username or password", "Alert!");
						}
					}
			}

			/******************************************************************************
			 * отслеживание ошибок mySQl и при соединении
			 ******************************************************************************/
			private function mySQLAlert (num:String, message:String):void
				{
				Alert.show(message, "mySQL Error! " + "Error #" + num);
				}

			private  function faultHandler(event:FaultEvent):void
			{
				var errorMessage:String = "Connection error: " + event.fault.faultString;
				if (event.fault.faultDetail)
				{
					errorMessage += "\n\nAdditional detail: " + event.fault.faultDetail;
				}
				Alert.show(errorMessage);
			}

		]]>
	</mx:Script>

	<mx:Label x="10" y="10" text="Login:" width="160"/>
	<mx:TextInput x="10" y="36" id="username"  width="160"/>
	<mx:Label x="10" y="66" text="Password:" width="160"/>
	<mx:TextInput 	id="password"
					x="10" y="92"
					displayAsPassword="true"
					enter="loginSubmitHanler()"
				  	width="160"/>

	<mx:Button 	id="cbSubmit"
				label="OK"
				click="loginSubmitHanler()"
			   	x="10" y="122"
			   	width="75"/>

	<mx:Button 	id="cbCancel"
				label="Cancel"
				click="closeWin()"
				x="95" y="122"
				width="75"
			    />

</mx:TitleWindow>

Внешний вид:
LoginWindow
Сопутствующие файлы: LoginEvent.as – Custom Event

package com.events
{
	import com.vo.GALLuserVO;

	import flash.events.Event;

	public class LoginEvent extends Event
	{
		public var userVO:GALLuserVO;

		public function LoginEvent(type:String, userVO:GALLuserVO)
		{
			super(type);
			this.userVO = userVO;
		}
	}
}

и GALLuserVO.as – value-object class

package com.vo
{
	public class GALLuserVO
	{
		public var usersUsername:String;
		public var usersFirstname:String;
		public var usersLastname:String;
		public var usersEmail:String;
		public var usersDepartment:String;
		public var usersAppointment:String;
		public var usersPermission:String;
	}
}

При успешном запросе мы получаем следующие данные в дебаге:
debuguserdata

или для отладки через Alert:
userdata

Для различных ситуаций с ошибками выводятся следующие алярмы.
1. Не прошла авторизация
error_user
2. Ошибка при коннекте с базой данных
error_usersql
3. Ошибка в синтаксисе SQL
error_syntax

Вроде как все. Готов выслушать предложения по улучшению данного модуля :)

Categories: Flex Tags: , , , , ,
  1. Alexey
    21 Ноябрь 2009 в 02:15 | #1

    Не подскажешь а как зделать 2 и более окон и чтобы между ними можно было переключатся и двигать их?

  2. 21 Ноябрь 2009 в 06:01 | #2

    Что есть окна? Браузера, Флеш-плеера, 2 панели внутри флеша? можешь уточнить что имеешь ввиду?

  3. Alexey
    21 Ноябрь 2009 в 11:24 | #3

    что нибудь похожее на titlewindows. Хотя если с помощью flex можно из одного окна открывать еще окна флеш-плеера это тоже очень интересно.

  4. 21 Ноябрь 2009 в 16:14 | #4

    Естественно, можно вызвать хоть 3 окна типа TitleWindow.
    Обрати внимание:
    в файле логики, где обрабатываем нажатие кнопки:
    // добавляем окно авторизации в главное приложение
    var loginForm:LoginWindow = LoginWindow(PopUpManager.createPopUp(this, LoginWindow, false));

    Последний параметр (true / false) управляет модальностью окна, то есть будет ли это окно блокировать доступ к другим окнам.

    Никто не мешает сделать еще одно окно, условно:
    var loginForm2:LoginWindow = LoginWindow(PopUpManager.createPopUp(this, LoginWindow, false));

    :) Можно двигать каждое в пределах окна приложения [createPopUp(this...)] или какой его отдельной части (вместо this).

    Изменение размеров… я как то не особо интересовался на эту тему. Погугли, ребята пишут свои расширения для этого, и если меня не подводит память в 4м Flexe – компонент Spark TitleWindow может это делать…

  5. McRain
    17 Март 2010 в 01:35 | #5

    Лучше уж сразу AMFPHP – а то переделывать будет муторно.

Я не робот.