分类: 编程

  • Shell遍历文件夹下所有文件,并将文件内容写入一个文件中

    Shell遍历文件夹下所有文件,并将文件内容写入一个文件中

    软件著作权要求提供代码文档,这里提供使用Shell遍历文件夹下所有文件,并将文件内容写入一个文件中的方法。

    #!/bin/bash
    dir="."
    target="./target.txt"
    # 过滤指定文件或文件夹
    filter=(node_modules out dist $target)
    
    listfile() {
        filelist=`ls $1`
        for file in $filelist
        do
            if [[ "${filter[@]}" =~ "$file" ]];then
                continue
            fi
    
            if [ -d $1/$file ];then
                listfile $1/$file
            else
                cat $1/$file >> $target
            fi
        done
    }
    
    listfile $dir
    
  • MySQL常用SQL语句

    MySQL常用SQL语句

    记录一些常用的MySQL语句,方便查找翻阅。

    1. 查看MySQL数据库磁盘占用大小

    select 
    TABLE_SCHEMA as '数据库', 
    concat(truncate(sum(data_length)/1024/1024,2),'MB') as '数据容量(MB)',
    concat(truncate(sum(index_length)/1024/1024,2),'MB') as '索引容量(MB)'
    from information_schema.tables
    group by TABLE_SCHEMA
    ORDER BY data_size desc
    

    2. 查看MySQL数据库中表的磁盘占用

    select  
    table_schema as '数据库',  
    table_name as '表名',  
    table_rows as '记录数',  
    truncate(data_length/1024/1024, 2) as '数据容量(MB)',  
    truncate(index_length/1024/1024, 2) as '索引容量(MB)'  
    from information_schema.tables  
    where table_schema='bwc_plsedu_com'
    order by data_length desc, index_length desc;
    

    3. MySQL创建、删除用户,授权、撤销授权

    create user user@host identified by 'password';
    # 授权
    grant all privileges on db.table to user@host;
    # 取消授权
    revoke all privileges on test.* from 'user'@'host';
    #删除用户
    drop user 'test'@'127.0.0.1';
    # 刷新权限使授权生效
    flush privileges;
    

    4. 性能检查

    -- 查看当前连接
    SHOW PROCESSLIST;
    
  • 网页、APP跳转应用商店

    网页、APP跳转应用商店

    安卓

    1. 跳转到应用页面:market://details?id=
    2. 跳转到搜索:market://search?q=

    IOS

    1. 应用页面:itms-apps://itunes.apple.com/app/id 114211089
  • Linux有线未托管问题

    Linux有线未托管问题

    今天发现在用的一个Linux开发机一直不能自动连接有线网络,显示“有线未托管”,查找测试了很多文章的解决方案都无法使用,可能更新后有了一些变化或者各自情况不同,这里记录一下个人生效的处理方式。

    sudo vim /etc/netplan/00-installer-config.yaml
    
    #文件中添加
    renderer: NetworkManager
    
    sudo netplan generate
    sudo netplan apply
    sudo reboot
    
  • Linux服务器Swap配置

    Linux服务器Swap配置

    简单记录文件形式的Swap使用与配置方式。

    1. 交换文件大小配置原则

    1. 内存<2G,配置实际内存的两倍
    2. 内存>2G,配置为4G即可
    3. 内存>4G,追求极致性能,不需要配置交换

    2. 创建交换文件

    # 创建一个名称为swap的文件,大小为1GB
    # if 输入文件名称,此处使用/dev/zero即可
    # of 输出文件名称,使用期望的文件名即可
    # bs 同时设置读入/输出的块大小为多少个字节
    # count 拷贝多少个块,块大小等于bs指定的字节数
    dd if=/dev/zero of=/swap bs=1M count=1024
    
    # 配置交换文件权限
    chmod 0600 /swap
    
    # 将文件设置为交换文件
    mkswap /swap
    
    # 启用指定交换文件
    swapon /swap
    
    # 查看交换文件状态
    swapon -s
    
    # 添加交换文件自动挂载
    echo "/swap swap swap defaults 0 0" >> /etc/fstab
    

    3. 删除交换文件

    # 关闭指定交换文件
    swapoff /swap
    
    # 删除文件
    rm /swap
    
    # 删除自动挂载配置
    vi /etc/fstab
    
  • Google Chrome扩展开发

    Google Chrome扩展开发

    Chrome扩展开发者控制台

    1. 需要支付一次性的5美元
    2. 需要使用非国内卡

    参考:

    1. Chrome开发者网站
  • Electron中数据持久化的选择

    Electron中数据持久化的选择

    Electron是一个基于Chromium的桌面应用程序框架,它可以让开发人员在不需要熟练掌握Web开发技术的情况下,快速地开发出高质量的桌面应用程序。在Electron中,开发人员可以使用各种各样的数据存储方式,包括文件系统、数据库等。其中,数据库是一种非常常见的数据存储方式,它可以方便地存储和管理各种数据,包括文本、图片、音频、视频等。

    文件存储

    本地文件适合用来存储一些配置相关的信息,常见的可用格式比如JSON、INI、Yaml、Toml等。

    IndexedDB

    IndexedDB,我觉得更适合用于调用服务端接口的缓存,或者极少在主线程使用的数据,否则来回传递感觉性能可能不太高(未经测试,但是结论应该不会有错)。

    有朋友之前问到怎么在主线程中使用IndexedDB,直接使用是不可能的哈,毕竟那是暴露在浏览器中的,并没有相关的Node实现。不过,其实IndexedDB在Chrome中也是使用SQLite实现的,如果需要保持同构,只需要实现一个简单的数据库中间层来隐藏底层的API或者按照IndexedDB的API来封装一下SQLite的调用即可。

    SQLite

    使用SQLite作为数据库可以让Electron应用程序更加轻量级和易于管理。SQLite是一种基于文件的数据库系统,它可以在不需要安装任何额外软件的情况下,在本地运行和管理数据库。这意味着,开发人员可以在Electron应用程序中使用SQLite数据库,而不必考虑复杂的数据库管理和同步问题。此外,SQLite还支持多种数据模型和查询语言,这可以让开发人员更加方便地存储和管理各种数据。 使用SQLite作为数据库还可以让Electron应用程序更加安全。由于SQLite是一种基于文件的数据库系统,它不会占用过多的系统资源,因此可以在不影响应用程序性能的情况下,存储和管理大量的数据。此外,SQLite还支持数据加密和数据备份,这可以让开发人员更加方便地保护应用程序数据的安全。 总之,使用SQLite作为数据库可以让Electron应用程序更加轻量级和易于管理,同时还可以让应用程序更加安全。如果您正在使用Electron开发桌面应用程序,并且需要存储和管理大量的数据,那么使用SQLite数据库将是一个非常不错的选择。

    其他(LocalStorage/SessionStorage)

    当然渲染进程还是可以使用LocalStorage这些,使用相对IndexedDB就方便很多,只是有大小限制,适合存储用户级别的个性化缓存数据(主题、语言等),其他类型的数据就不是很推荐了。

  • MySQL8 GTID双主配置

    MySQL8 GTID双主配置

    记录一下MySQL8中配置GTID双主的方式。

    需要添加以下配置信息:

    vim /etc/my.cnf
    # 添加
    [mysqld]
    # 两台服务器的server-id不能一致
    server-id=1
    gtid_mode=on
    enforce-gtid-consistency=true
    

    具体使用到的SQL语句:

    # 创建一个账号用于另一台主机复制数据
    # create user 'slave'@'0.0.0.0' identified by 'this is your password';
    
    # 授权
    grant REPLICATION SLAVE on *.* to 'slave'@'0.0.0.0';
    
    # 查看主机状态
    SHOW MASTER STATUS;
    
    # 以下为另一台服务器执行内容
    CHANGE REPLICATION SOURCE to
        SOURCE_HOST = '0.0.0.0',
        SOURCE_PORT = 3306,
        SOURCE_USER = 'slave',
        SOURCE_PASSWORD = 'this is your password';
    
    # 停止并重置复制
    STOP REPLICA;
    reset REPLICA;
    
    # 开始复制并查看复制状态
    START REPLICA;
    SHOW REPLICA STATUS;
    
  • PHP内置服务器与Serverless

    PHP内置服务器与Serverless

    PHP从5.4版本开始就提供了一个内置的WEB服务器,可以通过一个简单的命令php -S启动一个WEB服务器,极大简化了开发环境的搭建。

    到目前为止,官网文档对于内置服务器的使用依然建议用于开发环境,不建议用于生产环境,原因倒是很容易理解,主要有两个方面:

    1. 支持的MIME类型很少,5.4版本放出时只支持.htm和.svg(从5.5版本完善了大部分常见的MIME类型支持)

    2. 仅实现了基本功能,基本没有任何优化,是一个单线程进程(不过从7.4版本开始,内置服务器支持多进程的运行方式)

    从传统开发角度看,这样性能和功能的服务器确实很难应用于生产环境,但是伴随着Serverless的发展,感觉内置服务器的限制突然不是那么重要了。

    使用Serverless服务,不管是AWS Lambda,Google Function,还是国内阿里云的函数计算、腾讯云的云函数,我们关注的点不再聚焦于单机性能释放,而是变成了以下四个方面,我们要做的本质上变成了降低单请求的资源占用和执行时间

    1. 调用次数

    2. CPU时间

    3. 内存占用

    4. 执行时间

    5. 带宽

    我们可以逐个对比以下,

    1. 调用次数显然很难因为WEB服务器的变化有什么变化

    2. CPU时间上,内置服务器作为一个单进程应用,同样的逻辑在函数计算这样的环境下,较少了Nginx与FPM交互的网络开销、Nginx的运行开销,理论上内置服务器应该表现更好

    3. 内存占用方面,内置服务器不再需要运行Nginx,同样逻辑,应该也比传统部署方式占用更少一些

    4. 执行时间,Nginx+FPM需要启动两个进程,需要两个进程间的通信,很难与直接启动PHP进程更快

    5. 带宽基本不用对比,应该不会有什么变化,gzip完全可以在CDN层来实现

    从Serverless的角度看,内置服务器并不算是一个很差的选择,对比传统的运行方式可能更加合适一些,就是不太清楚不建议生产环境使用是否有除性能外的其他原因,回头去翻一翻PHP的issue。

    参考文章

    1. PHP-Built-in web server(https://www.php.net/manual/en/features.commandline.webserver.php

  • Nextcloud安全最佳实践

    Nextcloud安全最佳实践

    1. 复杂密码
    2. Suspicious Login
    3. 两步认证,启用至少一项
      1. *Two-Factor TOTP Provider
      2. *Two-Factor Authentication via Nextcloud Notification
      3. *Two-Factor WebAuthn
      4. Two-Factor Email
  • PostgreSQL常用SQL语句

    PostgreSQL常用SQL语句

    PostgreSQL与MySQL语法有一些细微差异,记录一下PostgreSQL常用的SQL语句。

    1. 创建数据库、用户,并授予用户权限

    # 创建用户并指定owner(不指定owner,对应的用户授权了也看不见)
    CREATE DATABASE xxx owner xxx;
    create user test with password 'test';
    
    # 授权
    GRANT ALL PRIVILEGES ON DATABASE xxx TO xxx;
    GRANT ALL PRIVILEGES ON all tables in schema public TO xxx;
    GRANT ALL ON SCHEMA public TO xxx;
    GRANT USAGE ON SCHEMA public TO xxx;
    
    # 重载配置,让修改生效
    SELECT pg_reload_conf();
    

    2. 删除数据库

    如果有授权信息,删除数据库时会报错,要删除数据库需要先取消授权。

    # 禁止连接
    UPDATE pg_database 
    SET datallowconn = 'false' 
    WHERE datname = 'xxx';
    
    # 关闭已连接进程
    SELECT pg_terminate_backend(pid)
    FROM pg_stat_activity
    WHERE datname = 'xxx';
    
    # 取消授权并删除用户
    revoke all on database postgres from xxx;
    revoke all on all tables in schema public from xxx;
    revoke all on schema public from xxx;
    revoke usage on schema public from xxx;
    
    # 删除用户(不取消授权也无法删除用户)
    drop role xxx;
    
    # 重载配置,让修改生效
    SELECT pg_reload_conf();
    

    3. 重命名用户、数据库

    # 重命名用户
    ALTER USER name RENAME TO new_name;
    
    # 重命名数据库
    ALTER DATABASE name RENAME TO new_name;
    

    4. 修改密码

    ALTER USER xxx WITH PASSWORD 'xxx';
    

    5. 其他常用

    # 统计当前所有连接数
    select count(1) from pg_stat_activity;
    
    # 查询当前连接数详细信息
    select * from pg_stat_activity;
    
    # 查询最大连接数
    show max_connections;
    
  • MySQL给已存在的主键字段添加自增AUTO_INCREMENT

    MySQL给已存在的主键字段添加自增AUTO_INCREMENT

    每次都记不起来,记录一下…

    # 添加自增约束
    alter table table_name modify column COLUMN_NAME COLUMN_TYPE auto_increment;
    # 配置自增起始值
    alter table table_name auto_increment=10000;
    
  • PHP中对象缓存方式的选择

    PHP中对象缓存方式的选择

    类似于Map的键值类型对象缓存对于提高应用的性能有很大的作用,实现此类缓存的方式也比较多,那么该如何选择对象缓存的方式呢?由于PHP常用的运行方式主要是基于FPM的形式,这篇文章暂不考虑常驻内存形式的缓存。

    一、基于文件系统实现缓存

    这应该是比较常见的一种形式,基于文件系统的缓存优点:

    • 不需要安装额外的扩展、中间件
    • 支持几乎所有运行环境
    • 支持文件锁

    缺点:

    • 相对内存形式的缓存方式,性能一般
    • 存在并发读写时,性能极差(并发写,使用文件锁的情况)
    • 占用磁盘容量
    • 不好统计键调用次数等

    适合的场景:单机运行,单键极少写请求,需要持久化的情况,比如动态页面的静态化。

    二、基于数据库实现缓存

    优点:

    • 支持几乎所有运行环境,仅需要安装对应数据库的驱动程序,大部分环境默认提供至少一种数据库驱动程序
    • 支持锁
    • 方便进行复杂的查询统计

    缺点:

    • 作为最常遇到的性能问题点,不太适合用于缓存场景
    • 读写性能一般

    适合的场景:无法控制宿主安装程序或者扩展。

    三、基于Redis/Memcached等中间件实现缓存

    优点:

    • 读写性能好
    • 支持集群运行
    • 支持多数据结构(Redis)
    • 本身支持缓存淘汰策略

    缺点:

    • 需要额外的中间件
    • 需要额外的扩展、包支持
    • 大多数主机环境不支持(可喜的是随着公有云的发展,主机环境正在被新的虚拟化方式替代)

    适合的场景:只要支持安装,适合绝大多数场景。

  • 好用的自托管应用

    好用的自托管应用

    1. WordPress

    几乎是博客/电商独立站首选,或许不是那么完美,生态肯定是最完善的。

    2. Nextcloud

    开源网盘,官方客户端同步功能很好用,提供webdav访问,可以搭配其他支持webdav的应用使用。

    3. VaultWarden

    基于RUST的开源BitWarden服务端实现,用于存储密码/密钥/MFA/FIDO等信息。

    4. Code Server

    开源在线VScode编辑器。

    5. Redis Insight

    redis管理工具

    6. CloudBeaver

    开源在线数据库管理工具

    7. Parse Platform

    开源支持多平台的BAAS服务。

  • APP分发前的准备工作

    APP分发前的准备工作

    1. 登录、注册、注销
    2. 隐私权政策和服务协议
    3. 登录注册页面弹窗(勾选已读服务协议和隐私权政策,弹窗动作必须)
    4. 应用市场和对应账号
      • 苹果开发者会员
      • 主体认证
      • 涉及收费可能需要ICP证
    5. 软著登记证
  • APP Store应用上架需要注意的点

    APP Store应用上架需要注意的点

    最近公司的应用上架APP Store过程中一直遇到审核问题,记录一下遇到的问题,方便后续其他应用开发避坑。

    1、与安卓通用的审核条件

    APP分发前的准备工作

    2、虚拟支付

    – 所有的虚拟商品直接使用苹果的内购方式付款,避免后续改造的问题(需要给苹果30%抽成)
    – 提前考虑宣传物料和价格在不同货币区域的展示,或者避免物料中包含价格
    – 至少审核阶段,不要在应用界面里放跳转到其他应用的链接,苹果审核会认为这涉及到其他支付方式

    3、强制登录问题

    微信小程序也是一样的要求,所以最好设计阶段就开始考虑这个问题。

    – 不需要用户信息的数据不设计为强制鉴权
    – 将引导用户登录放到用户进行必须鉴权的操作时

  • Debian配置自动清理Journal日志

    Debian配置自动清理Journal日志

    Debian系统上(红帽系Linux发行版应该也是一样的),systemd-journald 服务负责管理 journal 日志。这些日志可以占用大量的磁盘空间,特别是当系统持续运行并且产生大量日志条目时。可以配置 systemd-journald 的日志保留策略来自动清理这些日志。

    1. 编辑 systemd-journald 的配置文件

    systemd-journald 的主要配置文件是 /etc/systemd/journald.conf

    sudo vim /etc/systemd/journald.conf
    

    2. 配置日志保留策略

    在配置文件中,你可以设置以下选项来控制日志的保留:

    • SystemMaxUse=: 设置系统日志可使用的最大磁盘空间。例如,SystemMaxUse=50M 会限制系统日志使用最多50MB的磁盘空间。
    • SystemKeepFree=: 设置保留的空闲磁盘空间。例如,SystemKeepFree=1G 会确保至少有1GB的空闲磁盘空间不会被日志使用。
    • MaxRetentionSec=: 设置日志条目的最大保留时间。例如,MaxRetentionSec=1month 会自动删除超过一个月的日志条目。

    3. 重新加载配置并重启服务

    在修改配置文件后,你需要重新加载 systemd 的配置并重启 systemd-journald 服务。

    sudo systemctl daemon-reload
    
    sudo systemctl restart systemd-journald
    

    4. 检查配置是否生效

    使用 journalctl 命令来检查 journal 的当前状态和配置。

    journalctl --disk-usage # 查看当前占用空间
    
    journalctl --vacuum-size=50M  # 可以用这个命令手动清理日志到指定大小,但通常不需要这样做,因为自动清理应该已经配置好了。
    

    5. 监控磁盘使用情况

    为了确保你的日志清理策略按预期工作,建议定期监控服务器的磁盘使用情况。你可以使用 df 命令来检查磁盘空间的使用情况。

    6. 注意事项

    • 在修改任何系统配置文件之前,最好先备份原始文件。
    • systemd-journald 的日志清理策略是基于磁盘空间使用量或日志条目的保留时间来工作的,所以确保你设置的策略符合你的实际需求。
    • 如果你的系统上有大量的日志生成,并且磁盘空间有限,你可能还需要考虑其他日志管理策略,如将日志发送到远程日志服务器或定期归档旧日志。
  • 使用Docker Compose部署NextCloud和WordPress

    使用Docker Compose部署NextCloud和WordPress

    一、全局配置

    name: lnmp
    services:
      caddy:
        image: caddy:latest
        volumes:
          - ./www:/var/www/html
          - ./caddy/etc:/etc/caddy
          - ./caddy/data:/data
          - ./caddy/config:/config
        ports:
          - 80:80
          - 443:443/tcp
          - 443:443/udp
        logging:
          driver: "json-file"
          options:
            max-size: "10m"
            max-file: 3
        restart: always
    
      redis:
        image: redis:latest
        volumes:
          - ./redis/config:/etc/redis
          - ./redis/data:/data
        restart: always
        command: /etc/redis/redis.conf
    
      mysql:
        image: mysql:latest
        volumes:
          - ./mysql/config:/etc/mysql
          - ./mysql/data:/var/lib/mysql
          - ./mysql/mysql-files:/var/lib/mysql-files
        cap_add:
          - SYS_NICE
        security_opt:
          - seccomp:unconfined
        environment:
          MYSQL_ROOT_PASSWORD: password
        ports:
          - 3306:3306
        restart: always
    
      php:
        build: ./php
        volumes:
          - ./php/config:/usr/local/etc
          - ./php/logs:/var/log/php
          - ./www:/var/www/html
        depends_on:
          - caddy
          - mysql
          - redis
        cap_add:
          - SYS_PTRACE
        logging:
          driver: "json-file"
          options:
            max-size: "10m"
            max-file: 3
        restart: always
    
      imaginary:
        image: nextcloud/aio-imaginary:latest
        restart: always
        command: -concurrency 2 -enable-url-source
        environment:
          - PORT=9000
    

    1. PHP

    PHP官方的镜像启用和安装的扩展比较少,直接使用会导致WordPress和Nextcloud的健康检查一堆信息,所以使用Dockerfile来基于官方镜像构建一个专用的镜像,PHP需要的扩展包括:

    • gd(png/jpeg/gif/webp/avif)
    • imagick
    • opcache(考虑性能)
    • apcu(Nextcloud的本地缓存)
    • zip(影响WordPress插件安装)
    • redis(WordPress的对象缓存和Nextcloud的分布式缓存)
    • gmp
    • intl
    FROM registry.cn-beijing.aliyuncs.com/ianzhi/php:8.4-fpm-alpine
    
    # 配置国内镜像
    RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
    
    # 安装构建扩展相关依赖
    RUN apk add --no-cache --update --virtual .build-deps $PHPIZE_DEPS
    
    # MySQL
    RUN docker-php-ext-install pdo_mysql mysqli \
      && docker-php-ext-enable pdo_mysql mysqli
    
    # 常用扩展
    RUN docker-php-ext-install pcntl exif bcmath sysvsem \
        && docker-php-ext-enable opcache exif bcmath pcntl sysvsem
    
    # apcu
    RUN pecl install apcu && docker-php-ext-enable apcu
    
    # zip扩展
    RUN apk add --no-cache --update libzip=1.11.4-r0 libzip-dev=1.11.4-r0 unzip \
      && docker-php-ext-install zip \
      && docker-php-ext-enable zip
    
    # redis
    RUN pecl install https://pecl.php.net/get/redis-6.2.0.tgz \
      && docker-php-ext-enable redis
    
    # intl
    RUN apk add --no-cache --update icu icu-dev \
      && docker-php-ext-configure intl \
      && docker-php-ext-install intl \
      && docker-php-ext-enable intl
    
    # imagick
    RUN apk add --no-cache --update imagemagick-dev imagemagick-svg \
     && pecl install https://pecl.php.net/get/imagick-3.8.0.tgz \
     && docker-php-ext-enable imagick
    
    # gd
    RUN apk add --no-cache --update libpng libpng-dev libavif-dev libjpeg-turbo-dev freetype-dev freetype libjpeg-turbo libavif  \
      && docker-php-ext-configure gd --with-freetype --with-jpeg --with-avif \
      && docker-php-ext-install gd \
      && docker-php-ext-enable gd
    
    # ffmpeg nextcloud需要视频转码时启用
    # RUN apk add --no-cache ffmpeg
    
    # gmp nextcloud使用加密时使用
    # RUN apk add --no-cache --update gmp-dev \
    # && docker-php-ext-install gmp \
    # && docker-php-ext-enable gmp
    
    # pgsql
    # RUN apk add --no-cache --update libpq-dev postgresql-dev \
    #   && docker-php-ext-install pdo_pgsql \
    #   && docker-php-ext-enable pdo_pgsql
    
    # 删除构建依赖
    RUN apk del --no-network .build-deps
    
    # 配置文件
    RUN cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini
    
  • 使用微信小程序来实现扫码登录网站

    使用微信小程序来实现扫码登录网站

    微信小程序本身提供了openid等信息的无感知获取,基于此来实现微信扫码登录,主要包含以下几个步骤:

    1. WEB登陆页面的实现

    打开登录页面时,生成一个带有唯一ID的小程序码,小程序码图片加载以后,通过WebSocket或者轮询确认此唯一ID是否已经确认登陆或者超时。

    这一步比较简单,进入登录页面,通过调用生成小程序码接口,就可以生成一个带有特定参数的小程序码。

    通过图片的onload的属性,可以启动一个定时器或者WebSocket连接到后端,获取是否已经确认登陆或者超时过期。

    2. 微信小程序端的实现

    通过onLoad可以获取到携带的唯一ID,调用login接口后可以获取code,合并到一起提交到后端登陆接口,后端可以通过调用code获取到session信息,用以区分不同用户。

    查询到用户以后,将对应的用户标记为登陆状态即可,具体实现可以按照应用逻辑来。

    3. 后端的实现

    后端主要包括:

    1. 小程序码接口,用于展示小程序码图片
    2. 登录接口,接受code和唯一ID
    3. 状态查询接口,或者WebSocket服务,用于前端查询或者推送唯一ID过期或者确认登陆状态,实现登陆后的跳转。