diff --git a/server/auth.go b/server/auth.go index 84181dc..3cdedc4 100644 --- a/server/auth.go +++ b/server/auth.go @@ -5,7 +5,6 @@ import ( "polaris/db" "polaris/log" "polaris/pkg/utils" - "strings" "time" "github.com/gin-gonic/gin" @@ -23,16 +22,15 @@ func (s *Server) authModdleware(c *gin.Context) { c.Next() return } - - auth := c.GetHeader("Authorization") - if auth == "" { - log.Infof("token is not present, abort") + token, err := c.Cookie("token") + if err != nil { + log.Errorf("token error: %v", err) c.AbortWithStatus(http.StatusForbidden) return } - auth = strings.TrimPrefix(auth, "Bearer ") + //log.Debugf("current token: %v", auth) - token, err := jwt.ParseWithClaims(auth, &jwt.RegisteredClaims{}, func(t *jwt.Token) (interface{}, error) { + tokenParsed, err := jwt.ParseWithClaims(token, &jwt.RegisteredClaims{}, func(t *jwt.Token) (interface{}, error) { return []byte(s.jwtSerect), nil }) if err != nil { @@ -40,15 +38,15 @@ func (s *Server) authModdleware(c *gin.Context) { c.AbortWithStatus(http.StatusForbidden) return } - if !token.Valid { - log.Errorf("token is not valid: %v", auth) + if !tokenParsed.Valid { + log.Errorf("token is not valid: %v", token) c.AbortWithStatus(http.StatusForbidden) return } - claim := token.Claims.(*jwt.RegisteredClaims) + claim := tokenParsed.Claims.(*jwt.RegisteredClaims) if time.Until(claim.ExpiresAt.Time) <= 0 { - log.Infof("token is no longer valid: %s", auth) + log.Infof("token is no longer valid: %s", token) c.AbortWithStatus(http.StatusForbidden) return } @@ -61,7 +59,6 @@ type LoginIn struct { Password string `json:"password"` } - func (s *Server) Login(c *gin.Context) (interface{}, error) { var in LoginIn @@ -93,11 +90,23 @@ func (s *Server) Login(c *gin.Context) (interface{}, error) { if err != nil { return nil, errors.Wrap(err, "sign") } + c.SetSameSite(http.SameSiteNoneMode) + c.SetCookie("token", sig, 0, "/", "", true, false) return gin.H{ "token": sig, }, nil } +func (s *Server) Logout(c *gin.Context) (interface{}, error) { + if !s.isAuthEnabled() { + return nil, errors.New( "auth is not enabled") + } + + c.SetSameSite(http.SameSiteNoneMode) + c.SetCookie("token", "", -1, "/", "", true, false) + return nil, nil +} + type EnableAuthIn struct { Enable bool `json:"enable"` User string `json:"user"` diff --git a/server/server.go b/server/server.go index 4a2f03b..92f2b0c 100644 --- a/server/server.go +++ b/server/server.go @@ -63,6 +63,7 @@ func (s *Server) Serve() error { setting := api.Group("/setting") { + setting.GET("/logout", HttpHandler(s.Logout)) setting.POST("/general", HttpHandler(s.SetSetting)) setting.GET("/general", HttpHandler(s.GetSetting)) setting.POST("/auth", HttpHandler(s.EnableAuth)) diff --git a/ui/lib/main.dart b/ui/lib/main.dart index 865af62..66886f8 100644 --- a/ui/lib/main.dart +++ b/ui/lib/main.dart @@ -2,7 +2,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_adaptive_scaffold/flutter_adaptive_scaffold.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; -import 'package:shared_preferences/shared_preferences.dart'; import 'package:ui/activity.dart'; import 'package:ui/login_page.dart'; import 'package:ui/movie_watchlist.dart'; @@ -177,41 +176,30 @@ class _MainSkeletonState extends State { (BuildContext context, SearchController controller) { return [Text("dadada")]; }), - FutureBuilder( - future: APIs.isLoggedIn(), - builder: (context, snapshot) { - if (snapshot.hasData && snapshot.data == true) { - return MenuAnchor( - menuChildren: [ - MenuItemButton( - leadingIcon: const Icon(Icons.exit_to_app), - child: const Text("登出"), - onPressed: () async { - final SharedPreferences prefs = - await SharedPreferences.getInstance(); - await prefs.remove('token'); - if (context.mounted) { - context.go(LoginScreen.route); - } - }, - ), - ], - builder: (context, controller, child) { - return TextButton( - onPressed: () { - if (controller.isOpen) { - controller.close(); - } else { - controller.open(); - } - }, - child: const Icon(Icons.account_circle), - ); - }, - ); - } - return Container(); - }) + MenuAnchor( + menuChildren: [ + MenuItemButton( + leadingIcon: const Icon(Icons.exit_to_app), + child: const Text("登出"), + onPressed: () async { + await APIs.logout(); + }, + ), + ], + builder: (context, controller, child) { + return TextButton( + onPressed: () { + if (controller.isOpen) { + controller.close(); + } else { + controller.open(); + } + }, + child: const Icon(Icons.account_circle), + ); + }, + ) + ], ), useDrawer: false, diff --git a/ui/lib/movie_watchlist.dart b/ui/lib/movie_watchlist.dart index 1f7802d..2bb43d9 100644 --- a/ui/lib/movie_watchlist.dart +++ b/ui/lib/movie_watchlist.dart @@ -45,8 +45,8 @@ class _MovieDetailsPageState extends ConsumerState { fit: BoxFit.fitWidth, opacity: 0.5, image: NetworkImage( - "${APIs.imagesUrl}/${details.id}/backdrop.jpg", - headers: APIs.authHeaders))), + "${APIs.imagesUrl}/${details.id}/backdrop.jpg", + ))), child: Padding( padding: const EdgeInsets.all(10), child: Row( @@ -58,7 +58,6 @@ class _MovieDetailsPageState extends ConsumerState { child: Image.network( "${APIs.imagesUrl}/${details.id}/poster.jpg", fit: BoxFit.contain, - headers: APIs.authHeaders, ), ), ), diff --git a/ui/lib/providers/APIs.dart b/ui/lib/providers/APIs.dart index a28fe83..da7503e 100644 --- a/ui/lib/providers/APIs.dart +++ b/ui/lib/providers/APIs.dart @@ -2,8 +2,6 @@ import 'package:dio/dio.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; -import 'package:quiver/strings.dart'; -import 'package:shared_preferences/shared_preferences.dart'; import 'package:ui/providers/server_response.dart'; class APIs { @@ -26,6 +24,7 @@ class APIs { static final delDownloadClientUrl = "$_baseUrl/api/v1/downloader/del/"; static final storageUrl = "$_baseUrl/api/v1/storage/"; static final loginUrl = "$_baseUrl/api/login"; + static final logoutUrl = "$_baseUrl/api/v1/setting/logout"; static final loginSettingUrl = "$_baseUrl/api/v1/setting/auth"; static final activityUrl = "$_baseUrl/api/v1/activity/"; static final activityMediaUrl = "$_baseUrl/api/v1/activity/media/"; @@ -49,53 +48,20 @@ class APIs { return "http://127.0.0.1:8080"; } - static Dio? gDio; - static Map authHeaders = {}; - - static Future isLoggedIn() async { - return isNotBlank(await getToken()); - } - - static Future getToken() async { - var token = authHeaders["Authorization"]; - if (isBlank(token)) { - final SharedPreferences prefs = await SharedPreferences.getInstance(); - var t = prefs.getString("token"); - if (isNotBlank(t)) { - authHeaders["Authorization"] = t!; - token = t; - } - } - return token ?? ""; - } - - static Future getDio() async { - if (gDio != null) { - return gDio!; - } - var token = await getToken(); - + static Dio getDio() { var dio = Dio(); dio.interceptors.add(InterceptorsWrapper( - onRequest: (options, handler) { - options.headers['Authorization'] = token; - return handler.next(options); - }, onError: (error, handler) { if (error.response?.statusCode != null && error.response?.statusCode! == 403) { final context = navigatorKey.currentContext; if (context != null) { context.go('/login'); - gDio = null; } } return handler.next(error); }, )); - if (isNotBlank(token)) { - gDio = dio; - } return dio; } @@ -108,9 +74,19 @@ class APIs { if (sp.code != 0) { throw sp.message; } - final SharedPreferences prefs = await SharedPreferences.getInstance(); - var t = sp.data["token"]; - authHeaders["Authorization"] = "Bearer $t"; - prefs.setString("token", "Bearer $t"); + } + + static Future logout() async { + var resp = await getDio().get(APIs.logoutUrl); + + var sp = ServerResponse.fromJson(resp.data); + + if (sp.code != 0) { + throw sp.message; + } + final context = navigatorKey.currentContext; + if (context != null) { + context.go('/login'); + } } } diff --git a/ui/lib/search.dart b/ui/lib/search.dart index e586de2..dd1e971 100644 --- a/ui/lib/search.dart +++ b/ui/lib/search.dart @@ -50,7 +50,6 @@ class _SearchPageState extends ConsumerState { child: Image.network( "${APIs.tmdbImgBaseUrl}${item.posterPath}", fit: BoxFit.contain, - headers: APIs.authHeaders, ), ), ), diff --git a/ui/lib/system_page.dart b/ui/lib/system_page.dart index b36b374..c702577 100644 --- a/ui/lib/system_page.dart +++ b/ui/lib/system_page.dart @@ -49,9 +49,7 @@ class _SystemPageState extends ConsumerState { DataCell(Text((item.size ?? 0).readableFileSize())), DataCell(InkWell( child: const Icon(Icons.download), - onTap: () => launchUrl(uri, - webViewConfiguration: WebViewConfiguration( - headers: APIs.authHeaders)), + onTap: () => launchUrl(uri), )) ]); })); diff --git a/ui/lib/tv_details.dart b/ui/lib/tv_details.dart index 385f3dc..9c29eaa 100644 --- a/ui/lib/tv_details.dart +++ b/ui/lib/tv_details.dart @@ -155,8 +155,7 @@ class _TvDetailsPageState extends ConsumerState { fit: BoxFit.fitWidth, opacity: 0.5, image: NetworkImage( - "${APIs.imagesUrl}/${details.id}/backdrop.jpg", - headers: APIs.authHeaders))), + "${APIs.imagesUrl}/${details.id}/backdrop.jpg"))), child: Padding( padding: const EdgeInsets.all(10), child: Row( @@ -167,8 +166,7 @@ class _TvDetailsPageState extends ConsumerState { padding: const EdgeInsets.all(10), child: Image.network( "${APIs.imagesUrl}/${details.id}/poster.jpg", - fit: BoxFit.contain, - headers: APIs.authHeaders, + fit: BoxFit.contain ), ), ), diff --git a/ui/lib/welcome_page.dart b/ui/lib/welcome_page.dart index 8fe99ec..500f6b4 100644 --- a/ui/lib/welcome_page.dart +++ b/ui/lib/welcome_page.dart @@ -34,7 +34,10 @@ class WelcomePage extends ConsumerWidget { Container( height: MediaQuery.of(context).size.height * 0.6, alignment: Alignment.center, - child: const Text("啥都没有...", style: TextStyle(fontSize: 16),)) + child: const Text( + "啥都没有...", + style: TextStyle(fontSize: 16), + )) ] : List.generate(value.length, (i) { var item = value[i]; @@ -56,10 +59,8 @@ class WelcomePage extends ConsumerWidget { width: 140, height: 210, child: Image.network( - "${APIs.imagesUrl}/${item.id}/poster.jpg", - fit: BoxFit.fill, - headers: APIs.authHeaders, - ), + "${APIs.imagesUrl}/${item.id}/poster.jpg", + fit: BoxFit.fill), ), SizedBox( width: 140, diff --git a/ui/pubspec.lock b/ui/pubspec.lock index e8f9982..e51939c 100644 --- a/ui/pubspec.lock +++ b/ui/pubspec.lock @@ -89,22 +89,6 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.3.1" - ffi: - dependency: transitive - description: - name: ffi - sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21" - url: "https://pub.flutter-io.cn" - source: hosted - version: "2.1.2" - file: - dependency: transitive - description: - name: file - sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" - url: "https://pub.flutter-io.cn" - source: hosted - version: "7.0.0" flutter: dependency: "direct main" description: flutter @@ -325,30 +309,6 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.9.0" - path_provider_linux: - dependency: transitive - description: - name: path_provider_linux - sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 - url: "https://pub.flutter-io.cn" - source: hosted - version: "2.2.1" - path_provider_platform_interface: - dependency: transitive - description: - name: path_provider_platform_interface - sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" - url: "https://pub.flutter-io.cn" - source: hosted - version: "2.1.2" - path_provider_windows: - dependency: transitive - description: - name: path_provider_windows - sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 - url: "https://pub.flutter-io.cn" - source: hosted - version: "2.3.0" percent_indicator: dependency: "direct main" description: @@ -365,14 +325,6 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "8.3.0" - platform: - dependency: transitive - description: - name: platform - sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" - url: "https://pub.flutter-io.cn" - source: hosted - version: "3.1.5" plugin_platform_interface: dependency: transitive description: @@ -405,62 +357,6 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "2.5.1" - shared_preferences: - dependency: "direct main" - description: - name: shared_preferences - sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180 - url: "https://pub.flutter-io.cn" - source: hosted - version: "2.2.3" - shared_preferences_android: - dependency: transitive - description: - name: shared_preferences_android - sha256: "93d0ec9dd902d85f326068e6a899487d1f65ffcd5798721a95330b26c8131577" - url: "https://pub.flutter-io.cn" - source: hosted - version: "2.2.3" - shared_preferences_foundation: - dependency: transitive - description: - name: shared_preferences_foundation - sha256: "0a8a893bf4fd1152f93fec03a415d11c27c74454d96e2318a7ac38dd18683ab7" - url: "https://pub.flutter-io.cn" - source: hosted - version: "2.4.0" - shared_preferences_linux: - dependency: transitive - description: - name: shared_preferences_linux - sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa" - url: "https://pub.flutter-io.cn" - source: hosted - version: "2.3.2" - shared_preferences_platform_interface: - dependency: transitive - description: - name: shared_preferences_platform_interface - sha256: "22e2ecac9419b4246d7c22bfbbda589e3acf5c0351137d87dd2939d984d37c3b" - url: "https://pub.flutter-io.cn" - source: hosted - version: "2.3.2" - shared_preferences_web: - dependency: transitive - description: - name: shared_preferences_web - sha256: "9aee1089b36bd2aafe06582b7d7817fd317ef05fc30e6ba14bff247d0933042a" - url: "https://pub.flutter-io.cn" - source: hosted - version: "2.3.0" - shared_preferences_windows: - dependency: transitive - description: - name: shared_preferences_windows - sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59" - url: "https://pub.flutter-io.cn" - source: hosted - version: "2.3.2" sign_in_button: dependency: transitive description: @@ -626,14 +522,6 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "0.5.1" - xdg_directories: - dependency: transitive - description: - name: xdg_directories - sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d - url: "https://pub.flutter-io.cn" - source: hosted - version: "1.0.4" sdks: dart: ">=3.4.3 <4.0.0" flutter: ">=3.22.0" diff --git a/ui/pubspec.yaml b/ui/pubspec.yaml index f79abd5..42edd15 100644 --- a/ui/pubspec.yaml +++ b/ui/pubspec.yaml @@ -40,7 +40,6 @@ dependencies: flutter_riverpod: ^2.5.1 quiver: ^3.2.1 flutter_login: ^5.0.0 - shared_preferences: ^2.2.3 percent_indicator: ^4.2.3 intl: ^0.19.0 flutter_adaptive_scaffold: ^0.1.11+1