Jan*_*m B 4 .net vb.net multithreading winforms
在.NET 3.5 Winforms应用程序中,在用户提供用户名和密码后,我在CurrentPrincipal属性中设置了一个自定义主体,如下所示:
My.User.CurrentPrincipal = Service.GetPrincipal(username)
Run Code Online (Sandbox Code Playgroud)
这是在使用Invoke调用的方法中完成的,因为原始线程不是UI线程:
Invoke(New Action(AddressOf doLogin))
Run Code Online (Sandbox Code Playgroud)
但是,当我单击Winforms应用程序中的按钮时,CurrentPrincipal属性已恢复为其默认值,即当前Windows用户.
Dim lPrincipal = My.User.CurrentPrincipal ' not my custom principal
Run Code Online (Sandbox Code Playgroud)
显然,在设置主体时使用Invoke并不能解决问题.是否有另一种方法为CurrentPrincipal应用程序中的所有线程设置属性?
源代码重现问题:
Imports System.Security.Principal
Imports System.Threading
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim lThread As New Thread(AddressOf doLogin)
lThread.Start()
End Sub
Private Sub doLogin()
Invoke(New Action(AddressOf setPrincipal))
End Sub
Private Sub setPrincipal()
My.User.CurrentPrincipal = New CustomPrincipal
MsgBox(My.User.CurrentPrincipal.Identity.AuthenticationType) ' Custom
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
MsgBox(My.User.CurrentPrincipal.Identity.AuthenticationType) ' Default
End Sub
End Class
Public Class CustomPrincipal
Implements IPrincipal
Public ReadOnly Property Identity() As IIdentity Implements IPrincipal.Identity
Get
Return New CustomIdentity()
End Get
End Property
Public Function IsInRole(ByVal role As String) As Boolean Implements IPrincipal.IsInRole
Return True
End Function
End Class
Public Class CustomIdentity
Implements IIdentity
Public ReadOnly Property AuthenticationType() As String Implements IIdentity.AuthenticationType
Get
Return "Custom"
End Get
End Property
Public ReadOnly Property IsAuthenticated() As Boolean Implements IIdentity.IsAuthenticated
Get
Return True
End Get
End Property
Public ReadOnly Property Name() As String Implements IIdentity.Name
Get
Return "CustomName"
End Get
End Property
End Class
Run Code Online (Sandbox Code Playgroud)
Ken*_*art 11
而不是Thread.CurrentPrincipal(My.User.CurrentPrincipal),使用AppDomain.SetThreadPrincipal:
AppDomain.CurrentDomain.SetThreadPrincipal(principal)
Run Code Online (Sandbox Code Playgroud)
你正在与.NET框架中称为"调用上下文"的东西进行斗争.我需要挥动一下手,因为我完全不了解它.基本前提是当前的主体是.NET安全的大交易.它使沙箱工作,帮助隔离代码,使其不能做任何不安全的事情.代码运行在浏览器,手机,插件等等.
当前主体与线程Thread.CurrentPrincipal属性相关联.这使得Control.Begin/Invoke()变得棘手,某种插件可以通过使用它在该线程上运行代码来劫持程序主线程的权限.呼叫上下文是针对此的反制措施.您的代码正在更新调用上下文的主体,而不是线程.在调用的调用完成后,它位于位桶中,在Control.Invoke()的情况下,它不会流回原始线程.
为此找到一个解决方法现在让我感到困惑.它实际上必须是源自设置属性的主线程的代码,不会被调用.我只能想到一个愚蠢的修复,使用一毫秒的Timer:
Private Sub setPrincipal()
Timer1.Enabled = True
End Sub
Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick
Timer1.Enabled = False
My.User.CurrentPrincipal = New CustomPrincipal
MsgBox(My.User.CurrentPrincipal.Identity.AuthenticationType) ' Custom
End Sub
Run Code Online (Sandbox Code Playgroud)
它确实有效.要小心可能的比赛.
| 归档时间: |
|
| 查看次数: |
3476 次 |
| 最近记录: |