App内实现免登录访问网站

需求

App登录了,访问网站时就不需要在网站再次登录账号了,是不是感觉很神奇呢?

哈哈,康师傅也是这么觉得的!

image-20220110114230536

那么今天我们就来实现一下这个神奇的功能吧!

需求分析

既然我们App的持久化登录状态是通过保存 token ,访问 api 时携带 token 来实现的。

那么,我们是否也可以让网站在访问 api 接口的时候携带上 token 呢?

img

有的小伙伴可能想到了一个办法——拦截 WebView 的请求,然后给每个请求都添加上 token 。

确实,这是一个可行的办法,但是有点太麻烦了(我试过,不好弄)。

img

那么还有其它方法吗?当然有啦!

我们都知道,前端的登录状态保存一般是保存在 cookies 里的,所以我们打开阳光沙滩网站看看。打开网站 —> 按下 F12 —> Application —> Storage —> Cookies 。

看到 sob_token 这个字段了吗,这就是阳光沙滩的网站保存的 token 啦,其中比较关键的是 namevaluedomainpath 这几个字段。(这几个字段我们先复制下来,等下会用到)

image-20220110132518335

网站的 token 既然是从 cookies 里获取的,那我们在 WebView 访问网站之前给它设置对应的 cookie 不就好了?

QQ图片20220110134014

那么,我们要怎么才能给 WebView 设置 cookie 呢?

查官方文档嘛!

通过查询相关文档,我们发现了 CookieManager 这个类可以帮我们实现这个需求。

CookieManager 类的简介

1
public abstract class CookieManager extends Object

Manages the cookies used by an application’s WebView instances.

CookieManager represents cookies as strings in the same format as the HTTP Cookie and Set-Cookie header fields (defined in RFC6265bis).

译:

管理应用程序的 WebView 实例使用的 cookie。

CookieManager 以与 HTTP Cookie 和 set-Cookie 头字段(在 RFC6265bis 中定义)相同的格式将 Cookie 表示为字符串。

从上面的描述就可以看出来,我们的 WebView 在访问网页的时候会使用 CookieManager 来获取 cookie ,那么我们只需要在加载网页之前把 Cookie 设置到 CookieManager 中即可。

我们再捋一下逻辑:网站请求 api —> 获取 Cookie —> WebView —> CookieManager。

编码实现

img

核心代码在下面,想要全部代码请查看我的 gitee 仓库(仓库地址:https://gitee.com/anjiemo/sob-login-demo)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
/**
* author : A Lonely Cat
* github : https://github.com/anjiemo/SunnyBeach
* time : 2022/01/10
* desc : WebView 界面
*/
public class BrowserActivity extends AppCompatActivity {

private static final String URL = "url";
private WebView mWebView;

public static void start(Context context, String url) {
Intent intent = new Intent(context, BrowserActivity.class);
intent.putExtra(URL, url);
if (!(context instanceof Activity)) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
context.startActivity(intent);
}

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.browser_activity);
initView();
initData();
}

private void initData() {
Intent intent = getIntent();
String url = intent.getStringExtra(URL);
mWebView.loadUrl(url);
}

@SuppressLint("SetJavaScriptEnabled")
private void initView() {
mWebView = findViewById(R.id.web_view);
mWebView.setWebViewClient(new AppBrowserViewClient());
WebSettings settings = mWebView.getSettings();
// 设置启用 Javascript
settings.setJavaScriptEnabled(true);
// 设置 Dom 存储已启用
settings.setDomStorageEnabled(true);
}

private static class AppBrowserViewClient extends WebViewClient {

@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
injectCookie(url);
}

/**
* 注入 Cookie
* @param url 需要注入 cookie 的 url
*/
private void injectCookie(String url) {
// 获取 CookieManager 的单例实例
CookieManager manager = CookieManager.getInstance();
String apiTopDomain = StringUtil.getTopDomain(Constants.SUNNY_BEACH_API_BASE_URL);
String siteTopDomain = StringUtil.getTopDomain(Constants.SUNNY_BEACH_SITE_BASE_URL);
String apiCookie = getCookie(apiTopDomain);
String siteCookie = getCookie(siteTopDomain);
manager.setCookie(url, apiCookie);
manager.setCookie(url, siteCookie);
}

/**
* 根据 domain 获取 sob_token
* @param domain 顶级域名
* @return cookie
*/
public String getCookie(String domain) {
SobCacheManager manager = SobCacheManager.newInstance();
return new Cookie.Builder()
.name(SobCacheManager.SOB_TOKEN_NAME)
.value(manager.getSobToken())
.domain(domain)
.path("/")
.build()
.toString();
}
}
}

请同学们点赞、评论、打赏+关注啦~


App内实现免登录访问网站
https://blog.funkt.cn/2022/01/10/1480423866630176769/
作者
anjiemo
发布于
2022年1月10日
许可协议
未经作者授权,禁止转载