View State

如何查看viewstate

鼠标右键页面,然后view page source

源码中搜索viewstate,会找到一个隐藏的字段。

<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPaA8FDzhkNmJlYWE3ODdlY2ZhMxgFBRpjdGwwMCRjcGhNYWluJHVjUHJvZmlsZSRJZA8FATVkBSBjdGwwMCRjcGhNYWluJHVjUHJvZmlsZSRMYXN0TmFtZQ8FA+WNomQFG2N0bDAwJGNwaE1haW4kdWNQcm9maWxlJEFnZQ8FAjMyZAUhY3RsMDAkY3BoTWFpbiR1Y1Byb2ZpbGUkRmlyc3ROYW1lDwUG5L+K5rabZAUdY3RsMDAkY3BoTWFpbiR1Y1Byb2ZpbGUkTW9uZXkPBQwwLjAwMDAwMjU1MjBkq9Xg7eCkuRMKxXAWft9MqgH5A1AKB7Ai3JQcgVlh+OI=" />

还有可能搜到一个叫__VIEWSTATEGENERATOR的字段,不过这个不是viewstate

<input type="hidden" name="__VIEWSTATEGENERATOR" id="__VIEWSTATEGENERATOR" value="8EB90039" />

F12,然后在elements菜单中进行搜索

 

解密

通过这个页面,可以进行解密http://viewstatedecoder.azurewebsites.net/

需要注意是有可能只能部分解密

32 byte(s) left over, perhaps an HMACSHA256 signature?

 

浅谈ViewState

一、ViewState概述
① ViewState是基于webform的

② 在web窗体控件属性处设置runat = "server",这个控件会被附加一个隐藏的属性_ViewState,_ViewState存放了所有控件在ViewState中的状态值。

③ 页面会在输出时,自动添加下面的隐藏域:

value处的值只是base64编码并不是加密。

④ ViewState是一个名称/值的对象集合。

⑤ 当请求某个页面时,ASP.NET会把所有控件的状态序列化成一个字符串,然后作为窗体的隐藏属性送到客户端,当客户端将页面回传时,ASP.NET分析回传的窗体属性,并赋给控件对应的值。(恢复现场)

⑥ ViewState不能存储所有的数据类型,仅支持:String、Integer、Boolean、Array、ArrayList、Hashtable

 

 

防止篡改

How to Make ViewState Secure in ASP.NET

 

 

Understanding ASP.NET View State

ASP.NET View State Overview

 

 

What Is View State And How It Works In ASP.NET

Background 

A web application is stateless.
That means that a new instance of a page is created every time when we make a request to the server to get the page and after the round trip our page has been lost immediately.
It only happens because of one server, all the controls of the Web Page is created and after the round trip the server destroys all the instances. So to retain the values of the controls we use state management techniques.
 

State Management Techniques

 
They are classified into the following 2 categories,
 

 

What Is View State And How It Works In ASP.NET
 
Now I am explaining what View State is.
 

View State

 
View State is the method to preserve the Value of the Page and Controls between round trips. It is a Page-Level State Management technique. View State is turned on by default and normally serializes the data in every control on the page regardless of whether it is actually used during a post-back.
 
Now I am showing you an example of what the problem is when we don't use view state.
    //Declaration of a and b  
    public string a, b;  
    protected void Button1_Click(object sender, EventArgs e)  
    {  
        //TextBox1 and TextBox2 Value is Assigning on the variable a and b  
        a = TextBox1.Text;  
        b = TextBox2.Text;  
        //after clicking on Button TextBox value Will be Cleared  
        TextBox1.Text = TextBox2.Text = string.Empty;  
    }  
       
    protected void Button3_Click(object sender, EventArgs e)  
    {  
        //value of variable a and b is assingning on TextBox1 and Textbox2  
        TextBox1.Text = a;  
        TextBox2.Text = b;  
    }   

 

 
It only happens because all the controls are classes and on the server all the Control Objects are created and then after the round trip the Page is returned to the client's browser in HTML format and the objects are destroyed at the server.
 
After the Submit button is clicked the value of user name and password is submitted to the server.
We cannot restore the value again because after the postback the instance of the control is destroyed and on clicking of the Restore Button the server takes a new request and the server cannot restore the value of the TextBox.
 
 

Features Of View State

 
These are the main features of view state,
  1. Retains the value of the Control after post-back without using a session.
  2. Stores the value of Pages and Control Properties defined in the page.
  3. Creates a custom View State Provider that lets you store View State Information in a SQL Server Database or in another data store.
And now I am explaining the stored value in the View State and the remaining steps are the same as the previous.

 

    protected void Button1_Click(object sender, EventArgs e)  
    {  
        //Value of Textbox1 and TectBox2 is assigin on the ViewState  
        ViewState["name"] = TextBox1.Text;  
        ViewState["password"] = TextBox2.Text;  
        //after clicking on Button TextBox value Will be Cleared  
        TextBox1.Text = TextBox2.Text = string.Empty;  
    }  
    protected void Button3_Click(object sender, EventArgs e)  
    {  
        //If ViewState Value is not Null then Value of View State is Assign to TextBox  
        if (ViewState["name"] != null)  
        {  
            TextBox1.Text = ViewState["name"].ToString();  
        }  
        if (ViewState["password"] != null)  
        {  
             TextBox2.Text = ViewState["password"].ToString();  
        }  
    }    

 

After clicking on the Submit Button the value of user name and password is submitted in View State and the View State stores the value of user name and password during post-back.
 
After click on the Restore Button we can get the value again. The Value must be retained during post-back and the values are stored into a base 64 encoded string and this information is then put into the View State Hidden Field.

 

Data Objects That Can be Stored in View state

  1. String
  2. Boolean Value
  3. Array Object
  4. Array List Object
  5. Hash Table 
  6. Custom type Converters

Advantages of View State

  1. Easy to Implement.
  2. No server resources are required: The View State is contained in a structure within the page load.
  3. Enhanced security features: It can be encoded and compressed or Unicode implementation.

Disadvantages of View State

  1. Security Risk: The Information of View State can be seen in the page output source directly. You can manually encrypt and decrypt the contents of a Hidden Field, but It requires extra coding. If security is a concern then consider using a Server-Based state Mechanism so that no sensitive information is sent to the client.
  2. Performance: Performance is not good if we use a large amount of data because View State is stored in the page itself and storing a large value can cause the page to be slow.
  3. Device limitation: Mobile Devices might not have the memory capacity to store a large amount of View State data.
  4. It can store values for the same page only.

When We Should Use View State

  1. When the data to be stored is small.
  2. Try to avoid secure data.

 

 

 

转载于:https://www.cnblogs.com/chucklu/p/6943487.html

Fatal Exception: java.lang.IllegalArgumentException: Wrong state class, expecting View State but received class androidx.appcompat.widget.Toolbar$SavedState instead. This usually happens when two views of different type have the same id in the same hierarchy. This view's id is id/toolbar. Make sure other views do not use the same id. at android.view.View.onRestoreInstanceState(View.java:21043) at android.view.View.dispatchRestoreInstanceState(View.java:21015) at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:4063) at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:4069) at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:4069) at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:4069) at android.view.ViewGroup.dispatchRestoreInstanceState(ViewGroup.java:4069) at android.view.View.restoreHierarchyState(View.java:20993) at com.android.internal.policy.PhoneWindow.restoreHierarchyState(PhoneWindow.java:2185) at android.app.Activity.onRestoreInstanceState(Activity.java:1753) at android.app.Activity.performRestoreInstanceState(Activity.java:1706) at android.app.Instrumentation.callActivityOnRestoreInstanceState(Instrumentation.java:1356) at android.app.ActivityThread.handleStartActivity(ActivityThread.java:3618) at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:221) at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201) at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173) at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2187) at android.os.Handler.dispatchMessage(Handler.java:106) at android.os.Looper.loop(Looper.java:236) at android.app.ActivityThread.main(ActivityThread.java:8057) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:620) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1011) 线上崩溃分析
最新发布
07-02
<think>好的,我现在需要分析用户提供的这个Android崩溃日志。首先,崩溃类型是IllegalArgumentException,错误信息是“Wrong state class, expecting View Statebut received class androidx.appcompat.widget.Toolbar$SavedState instead.This usually happens whentwo views of differenttype have the sameid in the samehierarchy. This view's id is id/toolbar. Makesure other views donot use the sameid.”。看起来是视图状态恢复时的问题。首先,我需要理解这个错误的原因。根据错误信息,当两个不同类型的视图在同一个视图层级中使用了相同的ID时,就会发生这种情况。系统期望恢复某个视图的状态,但接收到的却是另一个不同类型的视图的状态。例如,可能有一个Toolbar和其他视图(比如LinearLayout)使用了相同的ID,导致在恢复状态时出现类型不匹配。 接下来,我需要检查用户提供的代码和上下文。用户之前讨论的是关于Parcelable异常的问题,但现在这个崩溃是另一个不同的问题,涉及视图ID冲突。用户可能在布局文件中重复使用了相同的ID,尤其是在包含多个不同类型的视图时。 可能的场景:用户可能在某个Activity或Fragment的布局中定义了一个ID为toolbar的视图,比如一个Toolbar,而在另一个布局文件(例如通过include或者动态加载的Fragment)中,可能有另一个不同类型的视图也使用了id/toolbar。当系统尝试恢复状态时,保存的状态属于Toolbar,但当前视图可能是另一个类型,导致类型不匹配。需要验证这一点,用户需要检查所有相关的XML布局文件,确认是否有多个不同类型的视图共享相同的ID。特别是检查主布局文件和被包含的布局文件(如通过<include>标签引入的),以及各个Fragment的布局文件。另外,用户可能在代码中动态修改了视图的类型,比如在运行时替换了某个容器中的视图,但没有更新对应的ID,或者没有处理状态保存和恢复的逻辑。 解决方案方面,首先建议用户检查所有布局文件,确保同一层级内的视图ID唯一。如果确实需要复用ID,应确保同一时间只有一个视图存在,或者在替换视图时处理好状态保存。此外,可以重写onSaveInstanceState和onRestoreInstanceState方法,自定义处理状态保存,避免冲突。 还需要考虑是否使用了ViewPager或Fragment切换导致的视图层级问题,不同Fragment可能使用了相同的ID,尤其是在动态加载的情况下。另外,检查是否有自定义视图组件可能引入了ID冲突。 总结步骤:1.检查所有相关布局文件,确认id/toolbar是否在多个不同类型的视图中使用。 2.检查是否有include标签或合并布局导致的重复ID。 3.确保在动态替换视图时,正确管理ID和状态保存。 4.如果使用Fragment,检查各个Fragment的布局是否与其他部分存在ID冲突。5.考虑在自定义视图中正确实现状态保存和恢复逻辑。最后,提供具体的修复建议和示例代码,帮助用户解决这个问题,并预防类似问题的发生。</think>### 崩溃原因深度分析 #### 异常类型:**`IllegalArgumentException`** ```java Wrong state class, expecting View State but received class androidx.appcompat.widget.Toolbar$SavedState ``` #### 核心问题定位 - **根本原因**:**两个不同类型的视图在同一个视图层级中使用了相同的 `id`**。 - **具体场景**: 系统在恢复视图状态时,发现 `id/toolbar` 对应的视图类型与保存的状态类型不一致(例如:原本是 `Toolbar`,但当前是 `LinearLayout` 或其他类型)。 --- ### 典型触发场景 1. **布局文件中重复 `id` 定义** - 示例: ```xml <!-- activity_main.xml --> <androidx.appcompat.widget.Toolbar android:id="@+id/toolbar" ... /> <!-- included_layout.xml --> <LinearLayout android:id="@+id/toolbar" <!-- ❌ 与 Toolbar 冲突 --> ... /> ``` - **问题**:`<include>` 标签引入的布局与父布局中的 `id` 冲突。 2. **Fragment 动态替换导致的 `id` 复用** - 示例: ```kotlin supportFragmentManager.beginTransaction() .replace(R.id.container, MyFragment()) // container ID 被多个 Fragment 复用 .commit() ``` - **问题**:不同 Fragment 的布局中使用了相同 `id`。 3. **自定义视图与系统组件 `id` 冲突** - 示例: ```xml <!-- 自定义视图 --> <com.example.CustomView android:id="@+id/toolbar" ... /> <!-- 系统 Toolbar --> <androidx.appcompat.widget.Toolbar android:id="@+id/toolbar" <!-- ❌ 冲突 --> ... /> ``` 4. **ViewPager + FragmentPagerAdapter 导致的视图复用** - **问题**:`ViewPager` 预加载机制可能导致不同页面的 `id` 冲突。 --- ### 修复方案 #### 方法 1:确保 `id` 唯一性 - **步骤**: 1. **全局搜索 `@+id/toolbar`**:检查所有布局文件、`<include>` 布局和 Fragment 的 XML。 2. **修改冲突 `id`**: ```xml <!-- 修复后的 included_layout.xml --> <LinearLayout android:id="@+id/linear_layout_toolbar" <!-- ✅ 修改为唯一 ID --> ... /> ``` #### 方法 2:避免动态替换视图时的 `id` 冲突 - **场景**:动态添加/替换视图时。 - **修复代码**: ```kotlin // 使用新布局时移除旧视图 val container = findViewById<ViewGroup>(R.id.container) container.removeAllViews() val newView = layoutInflater.inflate(R.layout.new_layout, container, false) container.addView(newView) ``` #### 方法 3:Fragment 布局 `id` 命名规范化 - **最佳实践**:为每个 Fragment 的根布局分配唯一 `id`。 ```xml <!-- fragment_a.xml --> <FrameLayout android:id="@+id/fragment_a_root" ... /> <!-- fragment_b.xml --> <FrameLayout android:id="@+id/fragment_b_root" ... /> ``` #### 方法 4:禁用视图状态保存(极端情况) - **适用场景**:明确不需要恢复视图状态。 - **修复代码**: ```kotlin override fun onSaveInstanceState(outState: Bundle) { // 不保存视图状态 super.onSaveInstanceState(outState) } ``` --- ### 调试工具推荐 1. **布局检查器(Layout Inspector)** - **路径**:Android Studio → `Tools` → `Layout Inspector` - **用途**:实时查看视图层级和 `id` 分布。 2. **日志打印视图层级** ```kotlin val decorView = window.decorView Log.d("ViewHierarchy", getViewHierarchy(decorView)) fun getViewHierarchy(view: View): String { val sb = StringBuilder() fun traverse(view: View, depth: Int) { sb.append(" ".repeat(depth * 2) + view.javaClass.simpleName + " ID: ${view.id}\n") if (view is ViewGroup) { for (i in 0 until view.childCount) { traverse(view.getChildAt(i), depth + 1) } } } traverse(view, 0) return sb.toString() } ``` --- ### 预防措施 | 场景 | 风险 | 推荐做法 | |------|------|----------| | 多布局文件共用 `id` | 视图状态冲突 | 命名规范(如 `toolbar_main`, `toolbar_sub`) | | Fragment 动态替换 | `id` 复用 | 使用唯一根布局 `id` | | ViewPager 预加载 | 状态混乱 | 在 `Fragment` 中重写 `setUserVisibleHint()` | | 自定义视图 | 与系统组件冲突 | 使用 `@+id/custom_` 前缀 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值