Sorry for the lack of information. What I did in my code is like from an
aspx page Save button clck event, I called a shared method AddNew of a
class, declared in PhotoGalleryUtility.vb. In that method, I did the saving
of gallery data into an SQL db. Then I call a private method in the same
class called CreateDir. There is where I put the code to create a folder for
the newly added gallery data. The folder is created inside
webroot/images/galleries/{0} where {0} is the galleryID in the database. I
do not need to do anything in terms of security here. The folder will be
created at the specified location on the server just fine.
Ok, that's the first part. My app also allows gallery deletion, which,
deletes gallery entry in the database, and also the corresponding folder in
the said location.
From the aspx page listing all available galleries, and every each of them
have their 'X' image button to initiate deletion process. Clicking this
image, will trigger the javascript 'yes/no' confirmation alert box, then
calls the datagrid_ItemCommand event. From there, i call Delete method in
the same class as above. (PhotoGalleryUtility.vb). In that method, I delete
the entry from the db, proceed to deleting the corresponding folder in the
location. The delete code is actually in different private method in the
class (DeleteDir), so here is the method:-
' *********************************************************************
' DeleteDir Methods (private)
' *********************************************************************
'
' Create directory in images folder.
'
' *********************************************************************
Private Shared Sub DeleteDir(ByVal gallery_id As Integer)
' Specify the directory you want to manipulate.
Dim path As String =
HttpContext.Current.Server.MapPath(String.Format("../{0}/{1}",
ABGGlobals.GalleriesPath, gallery_id))
' Determine whether the directory exists.
If Directory.Exists(path) Then
Dim imp As New ImpersonateUser
If imp.LogSelf() Then
' Delete the directory.
Directory.Delete(path, True)
imp.LogOff()
Else
Throw New Exception("Impersonation failed!")
End If
Else
Throw New Exception("Directory does not exist!")
End If
End Sub
'*********************************************************************
OK, here's my ImpersonateUser class, defined in ImpersonateUser.vb:-
'*********************************************************************
Imports System.Security.Principal
Imports System.Runtime.InteropServices
Public Class ImpersonateUser
Private _impersonationContext As WindowsImpersonationContext
Private Declare Function LogonUserA Lib "advapi32.dll" (ByVal
lpszUsername As String, _ ......................
Private Declare Auto Function DuplicateToken Lib "advapi32.dll" ( _
......................
Private Declare Auto Function RevertToSelf Lib "advapi32.dll" () As Long
Private Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal
handle As IntPtr) As Long
' *********************************************************************
' LogSelf Methods
' *********************************************************************
'
' Log current user.
'
' *********************************************************************
Public Function LogSelf() As Boolean
Dim currentWindowsIdentity As WindowsIdentity
HttpContext.Current.Session("name") = ""
HttpContext.Current.Session("test") = ""
currentWindowsIdentity = CType(HttpContext.Current.User.Identity,
WindowsIdentity) <============== The problematic line!
HttpContext.Current.Session("name") = currentWindowsIdentity.Name()
HttpContext.Current.Session("test") = "Session OK"
If currentWindowsIdentity.IsAuthenticated Then
_impersonationContext = currentWindowsIdentity.Impersonate()
Return True
Else
Return False
End If
End Function
' *********************************************************************
' LogOff Methods
' *********************************************************************
'
' Revert impersonation.
'
' *********************************************************************
Public Sub LogOff()
_impersonationContext.Undo()
End Sub
End Class
'*********************************************************************
I have tried passing the identity object from code behind of the aspx page
to the impersonateuser class so that i can skip the 'currentWindowsIdentity
= CType(HttpContext.Current.User.Identity, WindowsIdentity)' line all
together in the class. But in code behind file, the casting in line X :
'*********************************************************************
Private Sub dgrdGalleries_ItemCommand(ByVal source As Object, ByVal e As
System.Web.UI.WebControls.DataGridCommandEventArgs) Handles
dgrdGalleries.ItemCommand
Dim galleryID As Integer =
Fix(dgrdGalleries.DataKeys(e.Item.ItemIndex))
Select Case e.CommandName
Case "Delete"
lblError.Text = PhotoGalleryUtility.Delete(galleryID,
CType(HttpContext.Current.User.Identity,
System.Security.Principal.WindowsIdentity)) <=== X!!
Case "Up"
PhotoGalleryUtility.MoveUp(galleryID)
Case "Down"
PhotoGalleryUtility.MoveDown(galleryID)
End Select
End Sub
'*********************************************************************
keep producing the error:-
Server Error in '/' Application.
Specified cast is not valid.
Description: An unhandled exception occurred during the execution of the
current web request. Please review the stack trace for more information
about the error and where it originated in the code.
Exception Details: System.InvalidCastException: Specified cast is not valid.
This a lengthy post, and I'm tired of this casting error and thinking of
giving up this impersonation method... prefer the impersonate as specified
user/pwd/domain method anyway...
----------------------------------------------------------------------------
---- -----------------------------------------------------------------------
---------
Shan Plourde said:
Could it be related to where you are placing this in both the .aspx and
code behind? As more of an apples to apples comparison, did you code
this within a Page_Load() event handler first in your aspx page, then in
your code behind? Or, did you place them in different methods
altogether? If so, first start by ensuring that you have that apples to
apples comparison.
Otherwise, it is likely that the current user property is not yet set by
the .NET presentation framework depending on where you are trying to
access it from within your code behind. That would be my first guess.
The MSDN may have some tips on when this property is set. You may want
to look up HttpApplication and see if your code behind logic is getting
accessed after the appropriate HttpApplication AuthenticateRequest event
has been fired (or AuthorizeRequest)...
Also, ensure that you have System.Web in your using list in your code
behind. Hopefully that helps
Shan Plourde
Dale,
Maybe we are a bit off from the main question of my post which was why the
statement:-
currentWindowsIdentity = CType(HttpContext.Current.User.Identity,
System.Security.Principal.WindowsIdentity)
in code-behind produces error while
currentWindowsIdentity = CType(User.Identity,
System.Security.Principal.WindowsIdentity)
in aspx page does not.
---------------------------------------------------------------------------
-
---- ---------------------------------------------------------------------- -
---------
Duh, I don't know what I was thinking.
IsInRole is actually a method of the User object - well, actually the
IPrincipal object upon which the User is based.
Dale
Thanks for the tip. I'll try it tomorrow and see how it goes.
--------------------------------------------------------------------------
---- ---------------------------------------------------------------------
--
---------
Remember that by impersonating a specific user, you have to include
username
and password your code. This is not a good idea except in very
controlled
environments.
Set Anonymous Access off on the virtual folder in IIS, click Basic
Authentication off, and click Windows Integrated Authentication on.
And, of course, make sure your ACLs are set properly on the files and
folders for the users you want to have access.
Next, in the <system.web> section of your web.config for your web app,
include the following:
<identity impersonate="true" />
Now, your file access will be determined by the windows user from your
domain who is logged in.
You can also customize the access in code by using the
User.Identity.IsInRole("SomeSecurityUserOrGroupName") method -
accepting
or
rejecting the request based on the results.
Hope this helps,
Dale Preston
MCAD, MCSE, MCDBA
Sorry for late reply.. I took a day off yesterday.
I'm new to .NET and want to learn by creating my personal website
using
ASP.NET and VB.NET. In my application, I have photo galleries where
I
can
upload photos of certain events (galleries) into a folder in the
images
folder. Every events have their own folder to keep the photos. I
have
no
problem creating folders. But when it comes to deleting them, i got
'Access
denied' which probably because of security issues. I don't want to
change
anything on the server side, and resort to using impersonation.
From the samples given by MS KB at
http://support.microsoft.com/default.aspx?scid=kb;EN-US;306158, i
have
no
problem impersonating as the administrator account (I maintain the
server
in
the office), that is, the fourth example on the link titled
'Impersonate
a
Specific User in Code'. I came across the third example titled
'Impersonate
the Authenticating User in Code', (the code is given in my original
post)
and would like to try that method. That's when the error occurs.
Hope that you understand what I'm trying to say here. It's just the
purpose
of learning. I believe it should work somehow.
Thanks.
--------------------------------------------------------------------------
---- ---------------------------------------------------------------------
--
---------
I am not sure what you're trying to do with impersonation so it's
hard
to
tell you exactly how to do it but the User object in your web app
is
equivelent to a System.Security.Principal.IPrincipal object and
not
a
WindowsPrincipal object.
Likewise, the User.Identity is an IIdentity and not a
WindowsIdenity
object.
Can you post more about what you're trying to do?
Dale
Hi,
I have a class which basically do Impersonation in my web
application.
From
MS KB sample:-
++++++++++++++++++++code starts
Dim impersonationContext As
System.Security.Principal.WindowsImpersonationContext
Dim currentWindowsIdentity As
System.Security.Principal.WindowsIdentity
currentWindowsIdentity = CType(User.Identity,
System.Security.Principal.WindowsIdentity)
impersonationContext = currentWindowsIdentity.Impersonate()
'Insert your code that runs under the security context of the
authenticating
user here.
impersonationContext.Undo()
+++++++++++++++++++++code ends
since I need to implement this code in class.vb, I have to
change
the
line:-
currentWindowsIdentity = CType(User.Identity,
System.Security.Principal.WindowsIdentity)
to:-
currentWindowsIdentity =
CType(HttpContext.Current.User.Identity,
System.Security.Principal.WindowsIdentity)
But that produces error 'Specified cast is not valid.'. Is there
anything
that I miss here? Please help!
Thank you
--------------------------------------------------------------------------
---- ---------------------------------------------------------------------