添加 github oAuth 认证,添加错误提醒

This commit is contained in:
yifeng.yl
2019-05-29 18:46:12 +08:00
parent 9e7cd804e5
commit dbcdbab7d2
13 changed files with 197 additions and 67 deletions

View File

@ -14,6 +14,7 @@
<application
android:name="io.flutter.app.FlutterApplication"
android:label="fluttergo"
android:usesCleartextTraffic="true"
android:icon="@mipmap/ic_launcher_logo">
<activity
android:name=".MainActivity"

BIN
assets/images/gitHub.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@ -1,10 +1,14 @@
class Api{
// static const String BASE_URL = 'http://127.0.0.1:6001/';
static const String BASE_URL = 'http://flutter-go.alibaba.net/';
static const String BASE_URL = 'http://30.10.29.190:6001/';
// static const String BASE_URL = 'http://flutter-go.alibaba.net/';
static const String DO_LOGIN = BASE_URL+'doLogin';//登陆
static const String CHECK_LOGIN = BASE_URL+'checkLogin';//验证登陆
static const String LOGOUT = BASE_URL+'logout';//退出登陆
static const String GET_USER_INFO = BASE_URL+'getUserInfo';//获取用户信息
static const String RedirectIp = 'http://100.81.211.172/';
}

View File

@ -93,6 +93,7 @@ class _WidgetDemoState extends State<WidgetDemo> {
ApplicationEvent.event
.fire(CollectionEvent(widget.title, _router, true));
}
return;
}
print('删除错误');

View File

@ -5,3 +5,9 @@ class CollectionEvent{
// token uid...
CollectionEvent(this.widgetName,this.router,this.isRemove);
}
class UserGithubOAuthEvent{
final String loginName;
final bool isSuccess;
UserGithubOAuthEvent(this.loginName,this.isSuccess);
}

View File

@ -4,25 +4,37 @@ import './net_utils.dart';
import '../model/user_info.dart';
import 'package:flutter_go/api/api.dart';
class DataUtils{
class DataUtils {
// 登陆获取用户信息
static Future<UserInfo> doLogin(Map<String,String> params) async{
static Future doLogin(Map<String, String> params) async {
var response = await NetUtils.post(Api.DO_LOGIN, params);
print(response);
try {
UserInfo userInfo = UserInfo.fromJson(response['data']);
return userInfo;
} catch (err) {
return response['data'];
}
}
// 获取用户信息
static Future<UserInfo> getUserInfo(Map<String, String> params) async {
var response = await NetUtils.get(Api.GET_USER_INFO, params);
print(response);
UserInfo userInfo = UserInfo.fromJson(response['data']);
return userInfo;
}
// 验证登陆
static Future<bool> checkLogin() async{
static Future<bool> checkLogin() async {
var response = await NetUtils.get(Api.CHECK_LOGIN);
print('验证登陆:$response');
return response['success'];
}
// 退出登陆
static Future<bool> logout() async{
static Future<bool> logout() async {
var response = await NetUtils.get(Api.LOGOUT);
print('退出登陆 $response');
return response['success'];

View File

@ -17,12 +17,12 @@ class NetUtils {
var response;
// 设置代理 便于本地 charles 抓包
// (dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
// (HttpClient client) {
// client.findProxy = (uri) {
// return "PROXY 30.10.26.193:8888";
// };
// };
(dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =
(HttpClient client) {
client.findProxy = (uri) {
return "PROXY 30.10.29.190:8888";
};
};
Directory documentsDir = await getApplicationDocumentsDirectory();
String documentsPath = documentsDir.path;

View File

@ -32,8 +32,7 @@ class MainPage extends StatelessWidget {
'https://hbimg.huabanimg.com/9bfa0fad3b1284d652d370fa0a8155e1222c62c0bf9d-YjG0Vt_fw658',
scale: 15.0,
),
)
),
)),
centerTitle: true,
title: TabLayout(),
actions: <Widget>[
@ -44,6 +43,20 @@ class MainPage extends StatelessWidget {
})
],
),
drawer: Drawer(
child: new ListView(
children: <Widget>[
new ListTile(
title: new Text("欢迎"),
),
new Divider(),
new ListTile(
title: new Text("设置"),
trailing: new Icon(Icons.settings),
onTap: () {}),
],
),
),
body: TabBarViewLayout(),
// drawer: Drawer(
// child: MainLeftPage(),
@ -63,12 +76,9 @@ class TabLayout extends StatelessWidget {
return TabBar(
isScrollable: true,
//labelPadding: EdgeInsets.all(12.0),
labelPadding: EdgeInsets.only(top: 12.0,left: 12.0,right:12.0),
labelPadding: EdgeInsets.only(top: 12.0, left: 12.0, right: 12.0),
indicatorSize: TabBarIndicatorSize.label,
tabs: _allPages
.map((_Page page) =>
Tab(text: page.labelId))
.toList(),
tabs: _allPages.map((_Page page) => Tab(text: page.labelId)).toList(),
);
}
}

View File

@ -1,9 +1,16 @@
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:event_bus/event_bus.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:flutter_go/utils/data_utils.dart';
import 'package:flutter_go/views/home.dart';
import 'package:flutter_go/event/event_bus.dart';
import 'package:flutter_go/event/event_model.dart';
import 'package:flutter_go/model/user_info_cache.dart';
import 'package:flutter_go/routers/application.dart';
import 'package:flutter_go/routers/routers.dart';
class LoginPage extends StatefulWidget {
@override
@ -11,6 +18,11 @@ class LoginPage extends StatefulWidget {
}
class _LoginPageState extends State<LoginPage> {
_LoginPageState() {
final eventBus = new EventBus();
ApplicationEvent.event = eventBus;
}
// 利用FocusNode和_focusScopeNode来控制焦点 可以通过FocusNode.of(context)来获取widget树中默认的_focusScopeNode
FocusNode _emailFocusNode = new FocusNode();
FocusNode _passwordFocusNode = new FocusNode();
@ -47,27 +59,53 @@ class _LoginPageState extends State<LoginPage> {
} catch (err) {
print('读取用户本地存储的用户信息出错 $err');
}
ApplicationEvent.event.on<UserGithubOAuthEvent>().listen((event) {
if (event.isSuccess == true) {
print('请求接口');
// oAuth 认证成功
setState(() {
isLoading = true;
});
DataUtils.getUserInfo({'loginName': event.loginName}).then((result) {
print(result);
setState(() {
isLoading = false;
});
Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (context) => AppPage()),
(route) => route == null);
}).catchError((onError) {
print('获取身份信息 error:::$onError');
setState(() {
isLoading = false;
});
});
}
print('这是接受到的 event ${event.isSuccess} ${event.loginName}');
// _getList();
});
}
// 创建登录界面的TextForm
Widget buildSignInTextForm() {
return new Container(
decoration: new BoxDecoration(
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(8)),
),
width: MediaQuery.of(context).size.width * 0.8,
height: 190,
// * Flutter提供了一个Form widget它可以对输入框进行分组然后进行一些统一操作如输入内容校验、输入框重置以及输入内容保存。
child: new Form(
child: Form(
key: _signInFormKey,
child: new Column(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Flexible(
child: Padding(
padding: const EdgeInsets.only(
left: 25, right: 25, top: 20, bottom: 20),
child: new TextFormField(
child: TextFormField(
controller: _userNameEditingController,
//关联焦点
focusNode: _emailFocusNode,
@ -78,14 +116,14 @@ class _LoginPageState extends State<LoginPage> {
_focusScopeNode.requestFocus(_passwordFocusNode);
},
decoration: new InputDecoration(
icon: new Icon(
decoration: InputDecoration(
icon: Icon(
Icons.email,
color: Colors.black,
),
hintText: "Github 登录名",
border: InputBorder.none),
style: new TextStyle(fontSize: 16, color: Colors.black),
style: TextStyle(fontSize: 16, color: Colors.black),
//验证
validator: (value) {
if (value.isEmpty) {
@ -100,7 +138,7 @@ class _LoginPageState extends State<LoginPage> {
),
),
),
new Container(
Container(
height: 1,
width: MediaQuery.of(context).size.width * 0.75,
color: Colors.grey[400],
@ -108,18 +146,18 @@ class _LoginPageState extends State<LoginPage> {
Flexible(
child: Padding(
padding: const EdgeInsets.only(left: 25, right: 25, top: 20),
child: new TextFormField(
child: TextFormField(
controller: _passwordEditingController,
focusNode: _passwordFocusNode,
decoration: new InputDecoration(
icon: new Icon(
decoration: InputDecoration(
icon: Icon(
Icons.lock,
color: Colors.black,
),
hintText: "Github 登录密码",
border: InputBorder.none,
suffixIcon: new IconButton(
icon: new Icon(
suffixIcon: IconButton(
icon: Icon(
Icons.remove_red_eye,
color: Colors.black,
),
@ -128,7 +166,7 @@ class _LoginPageState extends State<LoginPage> {
),
//输入密码,需要用*****显示
obscureText: !isShowPassWord,
style: new TextStyle(fontSize: 16, color: Colors.black),
style: TextStyle(fontSize: 16, color: Colors.black),
validator: (value) {
if (value == null || value.isEmpty) {
return "密码不可为空!";
@ -142,7 +180,7 @@ class _LoginPageState extends State<LoginPage> {
),
),
),
new Container(
Container(
height: 1,
width: MediaQuery.of(context).size.width * 0.75,
color: Colors.grey[400],
@ -154,15 +192,15 @@ class _LoginPageState extends State<LoginPage> {
}
Widget buildSignInButton() {
return new GestureDetector(
child: new Container(
return GestureDetector(
child: Container(
padding: EdgeInsets.only(left: 42, right: 42, top: 10, bottom: 10),
decoration: new BoxDecoration(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(5)),
color: Theme.of(context).primaryColor),
child: new Text(
child: Text(
"LOGIN",
style: new TextStyle(fontSize: 25, color: Colors.white),
style: TextStyle(fontSize: 25, color: Colors.white),
),
),
onTap: () {
@ -186,7 +224,9 @@ class _LoginPageState extends State<LoginPage> {
});
DataUtils.doLogin({'username': username, 'password': password})
.then((result) {
print(result);
if(result.runtimeType == String){
throw result;
}
setState(() {
isLoading = false;
});
@ -198,20 +238,28 @@ class _LoginPageState extends State<LoginPage> {
.then((value) {
// print('存储成功:$value');
Navigator.of(context).pushAndRemoveUntil(
new MaterialPageRoute(builder: (context) => AppPage()),
MaterialPageRoute(builder: (context) => AppPage()),
(route) => route == null);
});
});
} catch (err) {
Navigator.of(context).pushAndRemoveUntil(
new MaterialPageRoute(builder: (context) => AppPage()),
MaterialPageRoute(builder: (context) => AppPage()),
(route) => route == null);
}
}).catchError((onError) {
print(onError);
}).catchError((errorMsg) {
setState(() {
isLoading = false;
});
Fluttertoast.showToast(
msg: errorMsg.toString(),
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.CENTER,
timeInSecForIos: 1,
backgroundColor: Theme.of(context).primaryColor,
textColor: Colors.white,
fontSize: 16.0
);
});
}
@ -275,7 +323,27 @@ class _LoginPageState extends State<LoginPage> {
),
buildSignInTextForm(),
buildSignInButton(),
SizedBox(height: 35.0),
SizedBox(height: 15.0),
new Container(
height: 1,
width: MediaQuery.of(context).size.width * 0.75,
color: Colors.grey[400],
margin: const EdgeInsets.only(bottom: 10.0),
),
FlatButton(
child: Text(
'Github OAuth 认证',
style: TextStyle(
color: Theme.of(context).primaryColor,
decoration: TextDecoration.underline),
),
onPressed: () {
// _launchURL('https://github.com/login/oauth/authorize?client_id=cfe4795e76382ae8a5bd&scope=user,public_repo');
Application.router.navigateTo(context,
'${Routes.webViewPage}?title=Github&url=${Uri.encodeComponent("https://github.com/login/oauth/authorize?client_id=cfe4795e76382ae8a5bd&scope=user,public_repo")}');
},
)
],
),
Positioned(

View File

@ -11,6 +11,7 @@ import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
import 'package:flutter_go/model/collection.dart';
import 'package:flutter_go/event/event_bus.dart';
import 'package:flutter_go/event/event_model.dart';
import 'package:flutter_go/api/api.dart';
class WebViewPage extends StatefulWidget {
final String url;
@ -21,6 +22,7 @@ class WebViewPage extends StatefulWidget {
}
class _WebViewPageState extends State<WebViewPage> {
final flutterWebviewPlugin = new FlutterWebviewPlugin();
bool _hasCollected = false;
String _router = '';
var _collectionIcons;
@ -30,6 +32,24 @@ class _WebViewPageState extends State<WebViewPage> {
@override
void initState() {
super.initState();
flutterWebviewPlugin.onUrlChanged.listen((String url) {
print('url change:$url');
if (url.indexOf('${Api.RedirectIp}loginSuccess') == 0) {
String loginName = url.substring(url.indexOf('=') + 1);
if (ApplicationEvent.event != null) {
ApplicationEvent.event.fire(UserGithubOAuthEvent(loginName, true));
}
flutterWebviewPlugin.close();
// 验证成功
} else if (url.indexOf('${Api.RedirectIp}loginFail') == 0) {
// 验证失败
if (ApplicationEvent.event != null) {
ApplicationEvent.event.fire(UserGithubOAuthEvent('', true));
}
flutterWebviewPlugin.close();
}
// if(url == '${Api.RedirectIp}loginSuccess')
});
_collectionControl
.getRouterByName(Uri.encodeComponent(widget.title.trim()))
.then((list) {

View File

@ -144,6 +144,13 @@ packages:
url: "https://pub.flutter-io.cn"
source: hosted
version: "0.3.4"
fluttertoast:
dependency: "direct main"
description:
name: fluttertoast
url: "https://pub.flutter-io.cn"
source: hosted
version: "3.1.0"
html:
dependency: "direct main"
description:

View File

@ -29,6 +29,7 @@ dependencies:
shared_preferences: ^0.4.3
flutter_spinkit: "^3.1.0"
path_provider: ^1.0.0
fluttertoast: ^3.1.0
dio: ^2.0.15
flutter_webview_plugin: ^0.3.4
cookie_jar: ^1.0.0