Android中的软件安全和逆向分析[一]—apk反编译破解以及java汇编代码读写

       在Android应用开发中,软件安全和逆向分析非常重要。试想如果一个优秀的APP应用没有建立完善的安全机制,从而很容易被黑客破解修改,一方面泄露了应用程序的核心技术,另一方面势必会对用户带来损害,从而造成大量的用户流失。如何反编译破解apk以及保护自己的软件免受反编译破解,是这个系列文章的主题。
       这篇文章主要从apk反编译破解和java汇编语言读写两个方面进行了Android中逆向分析的简述。俗话说:知己知彼,百战不殆。只有了解了apk的反编译破解过程,才能反方面进行加密处理从而避免自己的应用程序被反编译破解。本文通过使用apktool、dex2jar、jd-gui等工具实现了apk的反编译破解,然后修改破解后的java汇编语言、利用jarsigner进行二次签名从而达到改变apk功能的作用。

一、测试环境和工具

       点击即可下载相应工具

二、编写Android实例

       首先完成一个Android简单实例的编写,主要功能是输入一个序列号,如果输入序列号为1234,输出“恭喜你,注册成功!”,否则输出”对不起,序列号错误!”。
这里写图片描述

整个应用程序的工程目录如下,
这里写图片描述

activity_main.xml文件很简单,就两个控件EditText和Button。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.cracktest.MainActivity" >

    <EditText
        android:id="@+id/et_password"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:hint="请输入软件的序列号" />

    <Button
        android:id="@+id/click"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="确定" />

</LinearLayout>

MainActivity.java的实现也很简单,显示用Toast实现,

package com.example.cracktest;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class MainActivity extends Activity {

    private EditText et;
    private Button eb;

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        et = (EditText) findViewById(R.id.et_password);
        eb = (Button) findViewById(R.id.click);

        eb.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                String pwd = et.getText().toString().trim();

                if ("1234".equals(pwd)) {
                    Toast.makeText(MainActivity.this, "恭喜你,注册成功!", 0).show();
                } else {
                    Toast.makeText(MainActivity.this, "对不起,序列号错误!", 0).show();
                }
            }
        });
    }
}

模拟器上运行这个简单实例如下,
这里写图片描述
这里写图片描述

三、apk反编译破解

       假设我们现在要对上述工程生成的apk进行反编译破解,那么该怎么做呢?下面我们进行详细的流程描述。

  1. 导出APK到桌面
    DDMS->Devices->点击stop停止程序->File Explore->data->APP->.apk->点击导出键
    这里写图片描述

  2. .zip解压apk
    得到apk文件以后,若是直接修改后缀.apk为.zip文件然后解压查看,会发现解压完的文件在编辑器打开为乱码,只能寻求更好的方法来查看apk中的文件。
    这里写图片描述

  3. apktool打开apk
    apktool为apk逆向工程的软件,首先拷贝apk到apktool的目录下,然后cmd进入apktool的目录下,执行如下命令即可得到apk的全部的资源素材。
    这里写图片描述
    得到apk资源素材后,点击查看,C:\Users\Administrator\Desktop\apktool\com.example.cracktest-1\smali\com\example\cracktest
    这里写图片描述
    用编辑器打开MainActivity.smali文件如下,

.class public Lcom/example/cracktest/MainActivity;
.super Landroid/app/Activity;
.source "MainActivity.java"


# instance fields
.field private eb:Landroid/widget/Button;

.field private et:Landroid/widget/EditText;


# direct methods
.method public constructor <init>()V
    .locals 0

    .prologue
    .line 11
    invoke-direct {p0}, Landroid/app/Activity;-><init>()V

    return-void
.end method

.method static synthetic access$0(Lcom/example/cracktest/MainActivity;)Landroid/widget/EditText;
    .locals 1
    .parameter

    .prologue
    .line 13
    iget-object v0, p0, Lcom/example/cracktest/MainActivity;->et:Landroid/widget/EditText;

    return-object v0
.end method


# virtual methods
.method protected onCreate(Landroid/os/Bundle;)V
    .locals 2
    .parameter "savedInstanceState"

    .prologue
    .line 17
    invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V

    .line 18
    const/high16 v0, 0x7f03

    invoke-virtual {p0, v0}, Lcom/example/cracktest/MainActivity;->setContentView(I)V

    .line 20
    const/high16 v0, 0x7f08

    invoke-virtual {p0, v0}, Lcom/example/cracktest/MainActivity;->findViewById(I)Landroid/view/View;

    move-result-object v0

    check-cast v0, Landroid/widget/EditText;

    iput-object v0, p0, Lcom/example/cracktest/MainActivity;->et:Landroid/widget/EditText;

    .line 21
    const v0, 0x7f080001

    invoke-virtual {p0, v0}, Lcom/example/cracktest/MainActivity;->findViewById(I)Landroid/view/View;

    move-result-object v0

    check-cast v0, Landroid/widget/Button;

    iput-object v0, p0, Lcom/example/cracktest/MainActivity;->eb:Landroid/widget/Button;

    .line 23
    iget-object v0, p0, Lcom/example/cracktest/MainActivity;->eb:Landroid/widget/Button;

    new-instance v1, Lcom/example/cracktest/MainActivity$1;

    invoke-direct {v1, p0}, Lcom/example/cracktest/MainActivity$1;-><init>(Lcom/example/cracktest/MainActivity;)V

    invoke-virtual {v0, v1}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V

    .line 34
    return-void
.end method

       这就是反编译后生成的java汇编语言,发现读起来很困难,没事,这个在第三部分有讲解,那么我们怎么得到反编译后的java源代码呢?
4. dex2jar生成jar
在apk文件中,修改.apk后缀名为.zip,然后解压得到classes.dex文件,dex2jar工具的作用就是把dex文件转化为jar文件。把得到的classes.dex文件复制到dex2jar目录下,cmd执行命令如下,
这里写图片描述
5. jd-gui把jar转成java源码
打开jd-gui,直接将生成的classes_dex2jar.jar文件拖入到jd-gui中如下,
这里写图片描述
点击生成的java包即可查看apk里的java源码,仿真度很高
这里写图片描述

四、java汇编语言读写

       在上面使用apktool工具生成的.smali文件,打开发现是java汇编语言,很难读懂,下面就上述生成的汇编语言进行简单的说明。apktool生成了两个主要的.smali需要查看,分别为MainActivity.smaliMainActivity$1.smali

.class public Lcom/example/cracktest/MainActivity;//类生命,L表示对象类型
.super Landroid/app/Activity;//当前类的父类
.source "MainActivity.java"//源文件名字

//#就像c语言中的双斜杠,注释的作用
# instance fields//类成员变量
.field private eb:Landroid/widget/Button;

.field private et:Landroid/widget/EditText;


# direct methods
.method public constructor <init>()V //Activity构造方法,返回值为Void
    .locals 0//本地变量声明0个

    .prologue
    .line 11//这两句为自动生成行号等信息
    invoke-direct {p0}, Landroid/app/Activity;-><init>()V//直接调用,p0为this的意思

    return-void
.end method

.method static synthetic access$0(Lcom/example/cracktest/MainActivity;)Landroid/widget/EditText;
    .locals 1
    .parameter

    .prologue
    .line 13
    iget-object v0, p0, Lcom/example/cracktest/MainActivity;->et:Landroid/widget/EditText;

    return-object v0
.end method


# virtual methods
.method protected onCreate(Landroid/os/Bundle;)V //返回值为Void,null
    .locals 2
    .parameter "savedInstanceState"//方法参数

    .prologue
    .line 17
    invoke-super {p0, p1}, Landroid/app/Activity;->onCreate(Landroid/os/Bundle;)V

    .line 18
    const/high16 v0, 0x7f03

    invoke-virtual {p0, v0}, Lcom/example/cracktest/MainActivity;->setContentView(I)V

    .line 20
    const/high16 v0, 0x7f08

    invoke-virtual {p0, v0}, Lcom/example/cracktest/MainActivity;->findViewById(I)Landroid/view/View;

    move-result-object v0

    check-cast v0, Landroid/widget/EditText;

    iput-object v0, p0, Lcom/example/cracktest/MainActivity;->et:Landroid/widget/EditText;

    .line 21
    const v0, 0x7f080001

    invoke-virtual {p0, v0}, Lcom/example/cracktest/MainActivity;->findViewById(I)Landroid/view/View;

    move-result-object v0

    check-cast v0, Landroid/widget/Button;

    iput-object v0, p0, Lcom/example/cracktest/MainActivity;->eb:Landroid/widget/Button;

    .line 23
    iget-object v0, p0, Lcom/example/cracktest/MainActivity;->eb:Landroid/widget/Button;

    new-instance v1, Lcom/example/cracktest/MainActivity$1;//新实例对象类型为com/example/cracktest/MainActivity$1

    invoke-direct {v1, p0}, Lcom/example/cracktest/MainActivity$1;-><init>(Lcom/example/cracktest/MainActivity;)V

    invoke-virtual {v0, v1}, Landroid/widget/Button;->setOnClickListener(Landroid/view/View$OnClickListener;)V

    .line 34
    return-void
.end method
.class Lcom/example/cracktest/MainActivity$1;//类生命,L表示对象类型
.super Ljava/lang/Object;//当前类的父类
.source "MainActivity.java"//源文件名字

//#就像c语言中的双斜杠,注释的作用
# interfaces //实现接口
.implements Landroid/view/View$OnClickListener;


# annotations
.annotation system Ldalvik/annotation/EnclosingMethod;
    value = Lcom/example/cracktest/MainActivity;->onCreate(Landroid/os/Bundle;)V
.end annotation

.annotation system Ldalvik/annotation/InnerClass;
    accessFlags = 0x0
    name = null
.end annotation


# instance fields//类成员变量
.field final synthetic this$0:Lcom/example/cracktest/MainActivity;


# direct methods //Activity构造方法
.method constructor <init>(Lcom/example/cracktest/MainActivity;)V //Activity构造方法,返回值为Void
    .locals 0 //本地变量声明0个
    .parameter

    .prologue
    .line 1 //这两句为自动生成行号等信息
    iput-object p1, p0, Lcom/example/cracktest/MainActivity$1;->this$0:Lcom/example/cracktest/MainActivity;

    .line 23
    invoke-direct {p0}, Ljava/lang/Object;-><init>()V //直接调用,p0为this、Activity的意思

    return-void
.end method


# virtual methods
.method public onClick(Landroid/view/View;)V //onClick事件处理函数,V代表返回值为空
    .locals 4 //需要声明4个本地变量
    .parameter "v"//参数为view v

    .prologue
    const/4 v3, 0x0

    .line 25
    //调用p0里面的方法
    iget-object v1, p0, Lcom/example/cracktest/MainActivity$1;->this$0:Lcom/example/cracktest/MainActivity;

    #getter for: Lcom/example/cracktest/MainActivity;->et:Landroid/widget/EditText;
    invoke-static {v1}, Lcom/example/cracktest/MainActivity;->access$0(Lcom/example/cracktest/MainActivity;)Landroid/widget/EditText;

    move-result-object v1

    invoke-virtual {v1}, Landroid/widget/EditText;->getText()Landroid/text/Editable;//返回值为Editable

    move-result-object v1

    invoke-interface {v1}, Landroid/text/Editable;->toString()Ljava/lang/String;

    move-result-object v1

    invoke-virtual {v1}, Ljava/lang/String;->trim()Ljava/lang/String;

    move-result-object v0 //由EditText->Editable getText()->toString()->trim(),返回值为v0

    .line 27
    .local v0, pwd:Ljava/lang/String;
    const-string v1, "1234"  //定义常量,名字v1,值为1234

        //比较v1和v0的值
    invoke-virtual {v1, v0}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z //相等返回非0

    move-result v1

    if-eqz v1, :cond_0 //如果equal 0,不相等,执行cond_0逻辑

    .line 28
    iget-object v1, p0, Lcom/example/cracktest/MainActivity$1;->this$0:Lcom/example/cracktest/MainActivity;

    const-string v2, "\u606d\u559c\u4f60\uff0c\u6ce8\u518c\u6210\u529f\uff01" //如果相等,执行这个逻辑

    invoke-static {v1, v2, v3}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;

    move-result-object v1

    invoke-virtual {v1}, Landroid/widget/Toast;->show()V

    .line 32
    :goto_0
    return-void

    .line 30
    :cond_0
    iget-object v1, p0, Lcom/example/cracktest/MainActivity$1;->this$0:Lcom/example/cracktest/MainActivity;

    const-string v2, "\u5bf9\u4e0d\u8d77\uff0c\u5e8f\u5217\u53f7\u9519\u8bef\uff01" //可以测试这个字符串,控制台打印

    invoke-static {v1, v2, v3}, Landroid/widget/Toast;->makeText(Landroid/content/Context;Ljava/lang/CharSequence;I)Landroid/widget/Toast;

    move-result-object v1

    invoke-virtual {v1}, Landroid/widget/Toast;->show()V

    goto :goto_0
.end method

在上述分析中,如果v1和v0相等,则执行逻辑
const-string v2, “\u606d\u559c\u4f60\uff0c\u6ce8\u518c\u6210\u529f\uff01” //如果相等,执行这个逻辑
这句话是什么意思呢?我们可以自己写个java Test测试一下这个字符串,
这里写图片描述

五、修改反编译后的汇编语言文件

       假设我们现在得到了一个apk反编译后的java汇编语言,如果修改它使的改变它的功能。就上面这个列子而言,如果输入字符串为1234,则显示注册成功,否则显示序列号错误。在汇编语言中它实现的逻辑如下,

if-eqz v1, :cond_0 //如果equal 0,不相等,执行cond_0逻辑

如果v1和v0的比较返回值为0,即eqz为equal 0的话,执行显示cond_0,显示序列号错误。。。
修改if从句为

if-nez v1, :cond_0 //如果not equal 0,相等,执行cond_0逻辑

意思是说,如果v1和v0的比较不为0,即v1,v0相等,让它显示序列号错误,相当于和原来的逻辑相反了。
C:\Users\Administrator\Desktop\apktool\com.example.cracktest-1\smali\com\example\cracktest\MainActivity$1.smali文件中按照上述修改if从句。然后cmd进入apktool目录下,执行命令如下,
这里写图片描述

生成new.apk新的apk文件后,我们将之部署到模拟器上测试,找到adb安装目录后,cmd执行如下命令,
这里写图片描述

结果安装解析失败,原因没有签名证书,为什么呢?
点击查看原来的和新的apk文件,我们发现new.apk文件中没有META-INF文件,
这里写图片描述

META-INF文件夹为应用程序的签名。

为了解决安装apk失败的问题,我们要给new.apk进行签名。
将new.apk复制到signapk目录下,cmd中执行如下命令生成out.apk文件,
这里写图片描述
这里写图片描述

在out.apk中已经生成了META-INF文件夹,最后安装out.apk到模拟器上,
这里写图片描述
还是失败,因为原来模拟器上安装过这个软件,需要重新卸载掉,然后安装就可以了!

模拟器上卸载程序有两种方法:

  • 直接在模拟器中点击menu–>settings –> Applications –> Manage Applications 中点击你需要卸载的apk(就是你的应用软件)–>Uninstall;
  • 进入内嵌的linux,去data/app目录下删除 apk文件,这种方法可以批量删除
    adb shell
    cd data
    cd app
    rm ApplicationName.apk

卸载之后,重新进行安装如下,
这里写图片描述

最后在模拟器上测试结果展示
这里写图片描述
这里写图片描述

显示结果正好和原来结果相反,证明我们之前修改的.smali汇编语言文件,起了作用。

实际反汇编破解apk过程中,还是用dex2jar工具比较好,如果一个工程应用程序很复杂,那么直接查看汇编语言文件.smali会是项庞大的工程。no zuo no die !

六、参考引用

android apk反编译详解
Android APK反编译就这么简单 详解(附图)
Android APK反编译详解(附图)
谈谈android反编译和防止反编译的方法

未完待续。。。

<p> <strong><span style="font-size:20px;color:#FF0000;">本课程主要针对计算机相关专业正在做毕设学生与需要项目实战练习Java学习者</span></strong> </p> <p> <span style="color:#FF0000;"><strong><span style="font-size:18px;">1. 包含:<span style="color:#FFFF00;background-color:#FF0000;">项目源码、</span><span style="color:#FFFF00;background-color:#FF0000;">项目文档、数据库脚本、软件工具</span>等所有资料</span></strong></span> </p> <p> <span style="color:#FF0000;"><strong><span style="font-size:18px;">2. 手把手带你从零开始部署运行本套系统</span></strong></span> </p> <p> <span style="color:#FF0000;"><strong><span style="font-size:18px;">3. 该项目附带源码资料可作为毕设使用</span></strong></span> </p> <p> <span style="color:#FF0000;"><strong><span style="font-size:18px;">4. 提供技术答疑远程协助指导</span></strong></span><strong><span style="font-size:18px;"></span></strong> </p> <p> <br /> </p> <p> <span style="font-size:18px;"><strong>项目运行截图:</strong></span> </p> <p> <strong><span style="font-size:18px;">1)系统登陆界面</span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241015433522.png" alt="" /><br /> </span></strong> </p> <p> <strong><span style="font-size:18px;"><strong><span style="font-size:18px;">2)学生模块</span></strong></span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241015575966.png" alt="" /></span></strong> </p> <p> <strong><span style="font-size:18px;"><strong><span style="font-size:18px;">3)教师模块</span></strong></span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241016127898.png" alt="" /></span></strong> </p> <p> <strong><span style="font-size:18px;"><strong><span style="font-size:18px;">4)系统管理员</span></strong></span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241016281177.png" alt="" /></span></strong> </p> <p> <strong><span style="font-size:18px;"><img src="https://img-bss.csdn.net/202002241016369884.png" alt="" /></span></strong> </p> <p> <strong><span style="font-size:18px;"><br /> </span></strong> </p> <p> <strong><span style="font-size:18px;"><strong><span style="font-size:18px;">更多Java毕设项目请关注我毕设系列课程 <a href="https://edu.csdn.net/lecturer/2104">https://edu.csdn.net/lecturer/2104</a></span></strong></span></strong> </p> <p> <strong><span style="font-size:18px;"><br /> </span></strong> </p>
相关推荐
<p> 课程演示环境:Windows10  </p> <p> 需要学习<span>Ubuntus</span>系统<span>YOLOv4-tiny</span>同学请前往《<span>YOLOv4-tiny</span>目标检测实战:训练自己数据集》 <span></span> </p> <p> <span> </span> </p> <p> <span style="color:#E53333;">YOLOv4-tiny</span><span style="color:#E53333;">来了!速度大幅提升!</span><span></span> </p> <p> <span> </span> </p> <p> <span>YOLOv4-tiny</span>在<span>COCO</span>上性能可达到:<span>40.2% AP50, 371 FPS (GTX 1080 Ti)</span>。相较于<span>YOLOv3-tiny</span>,<span>AP</span><span>FPS</span>性能有巨大提升。并且,<span>YOLOv4-tiny</span>权重文件只有<span>23MB</span>,适合在移动端、嵌入式设备、边缘计算设备上部署。<span></span> </p> <p> <span> </span> </p> <p> 本课程将手把手地教大家使用<span>labelImg</span>标注使用<span>YOLOv4-tiny</span>训练自己数据集。课程实战分为两个项目:单目标检测(足球目标检测)多目标检测(足球梅西同时检测)。<span></span> </p> <p> <span> </span> </p> <p> 本课程<span>YOLOv4-tiny</span>使用<span>AlexAB/darknet</span>,在<span>Windows10</span>系统上做项目演示。包括:<span>YOLOv4-tiny</span>网络结构、安装<span>YOLOv4-tiny</span>、标注自己数据集、整理自己数据集、修改配置文件、训练自己数据集、测试训练出网络模型、性能统计<span>(mAP</span>计算<span>)</span>先验框聚类分析。 <span> </span> </p> <p> <span> </span> </p> <p> 除本课程《<span>Windows</span>版<span>YOLOv4-tiny</span>目标检测实战:训练自己数据集》外,本人推出了有关<span>YOLOv4</span>目标检测系列课程。请持续关注该系列其它视频课程,包括:<span></span> </p> <p> 《<span>Windows</span>版<span>YOLOv4</span>目标检测实战:训练自己数据集》<span></span> </p> <p> 《<span>Windows</span>版<span>YOLOv4</span>目标检测实战:人脸口罩佩戴识别》<span></span> </p> <p> 《<span>Windows</span>版<span>YOLOv4</span>目标检测实战:国交通标志识别》<span></span> </p> <p> 《<span>Windows</span>版<span>YOLOv4</span>目标检测:原理与源码解析》<span></span> </p> <p> <span> <img alt="" src="https://img-bss.csdnimg.cn/202007061503586145.jpg" /></span> </p> <p> <span><img alt="" src="https://img-bss.csdnimg.cn/202007061504169339.jpg" /><br /> </span> </p>
<p> <strong><span style="font-size:24px;">课程简介:</span></strong><br /> <span style="font-size:18px;">历经半个多月时间,</span><span style="font-size:18px;">Debug</span><span style="font-size:18px;">亲自撸 “企业员工角色权限管理平台” 终于完成了。正如字面意思,本课程讲解个真正意义上、企业级项目实战,主要介绍了企业级应用系统后端应用权限管理,其主要涵盖了六大核心业务模块、十几张数据库表。</span><span></span> </p> <p> <span style="font-size:18px;">其核心业务模块主要包括用户模块、部门模块、岗位模块、角色模块、菜单模块系统日志模块;与此同时,</span><span style="font-size:18px;">Debug</span><span style="font-size:18px;">还亲自撸了额外附属模块,包括字典管理模块、商品分类模块以及考勤管理模块等等,主要是为了更好地巩固相应技术栈以及企业应用系统业务模块开发流程!</span><span></span> </p> <p> <br /> </p> <p> <span style="font-size:24px;"><strong>核心技术栈列表</strong></span><span style="font-size:24px;"><strong>:</strong></span> </p> <p> <br /> </p> <p> <span style="font-size:18px;">值得介绍是,本课程在技术栈层面涵盖了前端后端大部分常用技术,包括</span><span style="font-size:18px;">Spring Boot</span><span style="font-size:18px;">、</span><span style="font-size:18px;">Spring MVC</span><span style="font-size:18px;">、</span><span style="font-size:18px;">Mybatis</span><span style="font-size:18px;">、</span><span style="font-size:18px;">Mybatis-Plus</span><span style="font-size:18px;">、</span><span style="font-size:18px;">Shiro(</span><span style="font-size:18px;">身份认证与资源授权跟会话等等</span><span style="font-size:18px;">)</span><span style="font-size:18px;">、</span><span style="font-size:18px;">Spring AOP</span><span style="font-size:18px;">、防止</span><span style="font-size:18px;">XSS</span><span style="font-size:18px;">攻击、防止</span><span style="font-size:18px;">SQL</span><span style="font-size:18px;">注入攻击、过滤器</span><span style="font-size:18px;">Filter</span><span style="font-size:18px;">、验证码</span><span style="font-size:18px;">Kaptcha</span><span style="font-size:18px;">、热部署插件</span><span style="font-size:18px;">Devtools</span><span style="font-size:18px;">、</span><span style="font-size:18px;">POI</span><span style="font-size:18px;">、</span><span style="font-size:18px;">Vue</span><span style="font-size:18px;">、</span><span style="font-size:18px;">LayUI</span><span style="font-size:18px;">、</span><span style="font-size:18px;">ElementUI</span><span style="font-size:18px;">、</span><span style="font-size:18px;">JQuery</span><span style="font-size:18px;">、</span><span style="font-size:18px;">HTML</span><span style="font-size:18px;">、</span><span style="font-size:18px;">Bootstrap</span><span style="font-size:18px;">、</span><span style="font-size:18px;">Freemarker</span><span style="font-size:18px;">、键打包部署运行工具</span><span style="font-size:18px;">Wagon</span><span style="font-size:18px;">等等,如下图所示:</span><span></span> </p> <img src="https://img-bss.csdn.net/201908070402564453.png" alt="" /> <p> <br /> </p> <p> <br /> </p> <p> <br /> </p> <p> <span style="font-size:24px;">课程内容与收益</span><span style="font-size:24px;">:</span><span></span> </p> <p> <br /> </p> <p> <img src="https://img-bss.csdn.net/201908070403452052.png" alt="" /> </p> <p> <span style="font-size:18px;">总来说,</span><span style="font-size:18px;">本课程是门具有很强实践性质“项目实战”课程,即“</span><span style="font-size:18px;">企业应用员工角色权限管理平台</span><span style="font-size:18px;">”,主要介绍了当前企业级应用系统员工、部门、岗位、角色、权限、菜单以及其他实体模块管理;其,还重点讲解了如何基于</span><span style="font-size:18px;">Shiro</span><span style="font-size:18px;">资源授权实现员工</span><span style="font-size:18px;">-</span><span style="font-size:18px;">角色</span><span style="font-size:18px;">-</span><span style="font-size:18px;">操作权限、员工</span><span style="font-size:18px;">-</span><span style="font-size:18px;">角色</span><span style="font-size:18px;">-</span><span style="font-size:18px;">数据权限管理;在课程最后,还介绍了如何实现键打包上传部署运行项目等等。如下图所示为本权限管理平台数据库设计图:</span> </p> <p> <span></span> </p> <p> <br /> </p> <p> <img src="https://img-bss.csdn.net/201908070404285736.png" alt="" /> </p> <p> <br /> </p> <p> <br /> </p> <p> <br /> </p> <p> <span style="font-size:18px;"><strong>以下为项目整体运行效果截图:</strong></span> <span></span> </p> <img src="https://img-bss.csdn.net/201908070404538119.png" alt="" /> <p> <br /> </p> <p> <img src="https://img-bss.csdn.net/201908070405002904.png" alt="" /> </p> <p> <br /> </p> <p> <br /> </p> <p> <img src="https://img-bss.csdn.net/201908070405078322.png" alt="" /> </p> <p> <br /> </p> <p> <img src="https://img-bss.csdn.net/201908070405172638.png" alt="" /> </p> <p> <br /> </p> <p> <img src="https://img-bss.csdn.net/201908070405289855.png" alt="" /> </p> <p> <br /> </p> <p> <img src="https://img-bss.csdn.net/201908070405404509.png" alt="" /> </p> <p> <br /> </p> <p> <img src="https://img-bss.csdn.net/201908070405523495.png" alt="" /> </p> <p> <br /> </p> <p> <br /> </p> <p> <br /> </p> <p style="text-align:left;"> <span style="font-size:18px;">值得是,在本课程,</span><span style="font-size:18px;">Debug</span><span style="font-size:18px;">也向各位小伙伴介绍了如何在企业级应用系统业务模块开发,前端到后端再到数据库,最后再到服务器上线部署运行等流程,如下图所示:</span><span></span> </p> <img src="https://img-bss.csdn.net/201908070406328884.png" alt="" /> <p> <br /> </p>
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页