728x90

로그인 구현 함수를 별도로 구현하지 않고, Retrofit 라이브러를 활용하여 간단하게 로그인 하는 코드로 변경했다.

 

import 'package:dio/dio.dart' hide Headers;
import 'package:login_ex/contact/repository/retrofit_url.dart';
import 'package:login_ex/contact/model/contact_result.dart';
import 'package:login_ex/user/model/login_response.dart';
import 'package:retrofit/retrofit.dart';
 
part 'rest_client.g.dart';
 
@RestApi(baseUrl: RetrofitURL.baseUrl)
abstract class RestClient {
  factory RestClient(Dio dio, {String baseUrl}) = _RestClient;
 
  @POST(RetrofitURL.mLogin)
  @FormUrlEncoded()
  Future<LoginResponse> userLogin(
      @Field() String keyword,
      @Field() String userID,
      @Field() String password,
      @Field() String uID,
      @Field() String mfoneNO,
      );
 
  @POST(RetrofitURL.contactData)
  @FormUrlEncoded()
  Future<ContactResult> postContactList(
      @Field() String keyword,
      @Field() String search,
      );
}

로그인 함수를 추가하고 터미널창에서 dart run build_runner build 를 다시 해서 rest_client.g.dart 파일을 업데이트 한다.

 

login_screen.dart 파일 코드

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:platform_device_id_v3/platform_device_id.dart';
import 'package:login_ex/common/repository/logging.dart';
import 'package:login_ex/common/res/data.dart';
import 'package:login_ex/common/utils/utils.dart';
import 'package:login_ex/contact/repository/rest_client.dart';
import 'package:login_ex/contact/view/contact_result_page.dart';
import 'package:login_ex/user/model/login_response.dart';
import 'package:login_ex/common/component/custom_text_form_field.dart';
import 'package:login_ex/common/res/colors.dart';
import 'package:login_ex/common/view/default_layout.dart';
import 'package:login_ex/user/repository/crypto_api.dart';
 
class LoginScreen extends StatefulWidget {
  const LoginScreen({super.key});
 
  @override
  State<LoginScreen> createState() => _LoginScreenState();
}
 
class _LoginScreenState extends State<LoginScreen> {
  String userid = '';
  String password = '';
  late String _deviceId;
  late final RestClient restClient;
 
  @override
  void initState() {
    super.initState();
    getDeviceUniqueId();
   loginRestInit();
  }
 
  Future<void> loginRestInit() async {
    Dio dio = Dio();
    dio.interceptors.add(LogInterceptor());
    dio.interceptors.add(const CustLogInterceptor(storage: storage));
    restClient = RestClient(dio);
  }
 
  Future<void> getDeviceUniqueId() async {
    String? deviceId;
    try {
      deviceId = await PlatformDeviceId.getDeviceId;
    } on PlatformException {
      deviceId = 'Failed to get deviceId.';
    }
 
    if (!mounted) return;
    setState(() {
      _deviceId = deviceId!;
      print("deviceId -> $_deviceId");
    });
  }
 
  @override
  Widget build(BuildContext context) {
    return DefaultLayout(
      child: SafeArea(
        top: true,
        bottom: false,
        child: Padding(
          padding: const EdgeInsets.symmetric(horizontal: 16.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              const SizedBox(height: 50.0),
              Image.asset(
                'asset/img/logo/logo.png',
                width: MediaQuery.of(context).size.width ,
              ),
              const SizedBox(height: 16.0),
              CustomTextFormField(
                hintText: '아이디를 입력하세요',
                obscureText: false,
                onChanged: (String value) {
                  userid = value.trim();
                },
              ),
              const SizedBox(height: 16.0),
              CustomTextFormField(
                hintText: '비밀번호를 입력하세요',
                obscureText: true,
                onChanged: (String value) {
                  password = value.trim();
                },
              ),
              const SizedBox(height: 16.0),
              ElevatedButton(
                onPressed: () async {
                  if(userid.isNotEmpty && password.isNotEmpty){
                    final mobileNO = await storage.read(key: MNumber);
 
                    LoginResponse result = await restClient.userLogin(
                        Crypto.AES_encrypt(Crypto.URLkey()),
                        Crypto.AES_encrypt(userid),
                        Crypto.RSA_encrypt(password),
                        _deviceId,
                        mobileNO!
                    );
                    if(result.status.contains('success')){
                      Utils.showSnackBar(context, '로그인 성공');
 
                      Navigator.of(context).push(
                        MaterialPageRoute(
                          builder: (_) => const ContactResultPage(),
                        ),
                      );
 
                    } else {
                      Utils.showAlert(context, result.status, result.message);
                    }
                  } else {
                    if(userid.isEmpty) {
                      Utils.showSnackBar(context, '아이디를 입력하세요');
                      return;
                    }
                    if(password.isEmpty){
                      Utils.showSnackBar(context, '비밀번호를 입력하세요');
                      return;
                    }
                  }
                },
                style: ElevatedButton.styleFrom(
                  backgroundColor: PRIMARY_COLOR,
                ),
                child: const Text(
                  '로그인',
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
 
}

 

 

PHP Session 을 처리하는 핵심코드를 구현하느라고 하루종일 삽질을 엄청했다.

구글링을 해도 제대로 된 것을 찾기가 어려웠고, CookieJar 커스텀으로 해결하려고 했으나 실패했다.

인프런 유료강좌 "[코드팩토리][중급] Flutter 진짜 실전"  강좌에서 언급된 코드가 생각이 나서 Access_Token 처리 대신에 Cookie 를 실어보내는 코드로 구현해보면 되겠다 싶어서 테스트해봤더니 성공했다.

블로그 이미지

Link2Me

,