我有一个包含4个项目的C#.net 3.5 WAP解决方案。 Web应用程序仅允许访问经理和HR。通过AD角色在web.config中授予授权。问题是所有管理员都可以访问应用程序的默认和第2页,但一位经理除了应该也能够访问Page2但不能(我会称他为特殊管理员)(但可以访问默认)。当尝试通过带有查询字符串的URL或通过默认页面上gridview行的select命令链接访问Page2时,specialmanager被重定向到自定义访问被拒绝页面。
的Web.config:
<authorization>
<allow roles="abc\hr, abc\managers, abc\it, abc\software tester"/>
<allow users="abc\specialmanager"/>
<!--<deny users="*"/>-->
<!--<allow users="*"/>--><!--default-->
</authorization>
<authentication mode="Windows"/>
<identity impersonate="true"/>
<customErrors mode="Off" defaultRedirect="~/Warning/AccessDenied.aspx">
<error statusCode="401" redirect="~/Warning/AccessDenied.aspx" />
</customErrors>
我尝试在执行重定向的方法中记录事件的历史记录,但是当我将错误记录放在try catch之外时,会发生HTTP 401.2错误。我已经检查了这个用户的SQL安全性,这是正确的 - 它与其他有访问权限的人一样。我已经验证此用户是被授予访问权限的AD组的成员。除了角色和相同的重定向到自定义访问被拒绝页面结果之外,我甚至允许此特定用户在Web配置中作为用户进行额外访问。 我在我的本地调试机器上冒充了这个用户,一切都很适合我,但是当他从服务器访问时他的机器上没有这样做,所以我无法真正复制他正在发生的事情。 我在每个页面的UI上都标识了用户名,并且他已正确识别。我不确定如何调试这个以找出应用程序认为他未被授权的原因。他的用户名必须与默认情况下网格行中列出的3个评论者中的1个匹配,如果他以这种方式访问它,那就是。
我只发布了可能相关的代码。我需要有关如何调试这个想法的帮助 - 任何想法?
获取用户名的代码:
//returns username portion of AD domain\username
public String GetUserName()
{
string curUser = Environment.UserName; //returns the logged-in account-name
//// impersonate a specific user during testing & development+
//if (curUser == "user1" || curUser == "user2")
//{
// curUser = "specialuser"; //local dev. Test as user specified here.
//}
//else
//{
// return curUser;
//}
return curUser;
}
//check current user's membership in AD groups that are allowed to view form
//ref: http://stackoverflow.com/questions/12029378/how-to-check-if-a-user-belongs-to-an-ad-group
public List<Boolean> CheckGroupMembership()
{
List<bool> blnIsMember = new List<bool>();
// set up domain context
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "abc");
// find a user
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, GetUserName());
for (int i = 0; i <= 3; i++)
{
// find the group in question
GroupPrincipal group = GroupPrincipal.FindByIdentity(ctx, _groupName[i]);
if (user != null)
{
// check if user is member of that group
if (user.IsMemberOf(group))
{
_IsMember[i] = true;
blnIsMember.Add(_IsMember[i]);//add array to list
}
else
{
_IsMember[i] = false;
blnIsMember.Add(_IsMember[i]);
}
}
}
return blnIsMember;
}
Page2,Page_Load()
protected void Page_Load(object sender, EventArgs e)
{
lblProgressStatus.Text = "";
//Handle security depending on user's point of entry; 1) from app's default page or 2)Page2, URL/clicking on link in email notificiation
//call I_CurrentUser interface
I_CurrentUser user = new ReviewData();
//get current username
strCurrentUser = user.GetUserName();
HttpContext.Current.Session["UserName"] = strCurrentUser;
//check current user's membership against AD groups needed to gain access
_IsMember = user.CheckGroupMembership();
//pass list to array
IsMember = _IsMember.ToArray(); //0=Admin, 1=Manager, 2=Developer, 3=Software Tester
//Hide Admin link if current user is NOT a member of admin[0], developer[2] or software tester[3] group
if (IsMember[0] == true || IsMember[2] == true || IsMember[3] == true)
{
//Link to Admin page
LinkButton3.Visible = true;
}
else
{
//Link to Admin page
LinkButton3.Visible = false;
}
//prepare to log any error messages
DataLib.ErrorLog oErrorLog = new DataLib.ErrorLog();
if (!IsPostBack)
{
try
{
if (!string.IsNullOrEmpty(Request.QueryString["ID"]))
{
string id = Request.QueryString["ID"];
intID = Convert.ToInt16(id);
string strID = intID.ToString();
ViewState["ID"] = strID;
Session["ID"] = strID;
AuthorizeCurrentUserSelection(intID, strCurrentUser);
/* If DocID is not in querystring, the user has accessed form via URL. Determine if DocID exists:
* if it doesn't, Insert prelim record, if it does, update formname.
* Else DocID is in querystring.*/
if (string.IsNullOrEmpty(Request.QueryString["DocID"]))
{
DataLib.EPRConn oGetID = new DataLib.EPRConn();
intDocID = oGetID.SelectDocID(intID); //if docid does not exist it will return integer 0
string strDocID = intDocID.ToString();
ViewState["SelectedDocID"] = strDocID;
Session["SelectedDocID"] = strDocID;
//Insert DocID when it's null or empty, or "0"
if (string.IsNullOrEmpty(strDocID) || strDocID == "0")
{
/*4/24/17 IMPORTANT: InsertDocID() executes an initial INSERT DocID into tbl1 and tbl2,
this allows Ratings to be UPDATED rather than INSERTED when radio buttons are
subsequently ticked and establishes DocID and FormName prior to first submit/save.*/
DataLib.EPRConn oInsertID = new DataLib.EPRConn();
oInsertID.InsertDocID(Convert.ToInt32(ViewState["ID"]), intDocID);
}
else //Update FormName if DocID exists.
{
FillCommentTextBoxes(strID);
FillMeritIncreaseTextBox();
//Update tbl1.FormName and tbl2 where FormName IS NULL (to assign names to older forms created prior to this app's launch
DataLib.EPRConn oFN = new DataLib.EPRConn();
oFN.UpdateFormName(intID);
}
}
else //DocID exists in querystring.
{
string dID = Request.QueryString["DocID"];
intDocID = Convert.ToInt16(dID);
string strDocID = intDocID.ToString();
ViewState["SelectedDocID"] = strDocID;
Session["SelectedDocID"] = strDocID;
FillCommentTextBoxes(strID);
FillMeritIncreaseTextBox();
//Update FormName in 2 tables where FormName IS NULL (to assign names to older forms created prior to this app's
DataLib.EPRConn oFN = new DataLib.EPRConn();
oFN.UpdateFormName(intID);
}
重定向到Page2的代码:
//pass form ID and viewing supervisor/current user
protected void AuthorizeCurrentUserSelection(int ID, string supUserName)
{
//Create a list of strings to hold up to 3 reviewers of selected employee
List<string> strLine = new List<string>();
//prepare to log any errors thrown
DataLib.ErrorLog oErrorLog = new DatLib.ErrorLog();
try
{
//return all rows from tbl
DataLib.EPRConn oAuth = new DataLib.EPRConn();
strLine = oAuth.SelectSupervisorUserName(eID, supUserName);
string[] arr = strLine.ToArray();
string strLevel1 = arr[0];
string strLevel2 = arr[1];
string strLevel3 = arr[2];
//0=Admin, 1=Manager, 2=Developer, 3=Software Tester.
if (IsMember[0] == true || IsMember[2] == true || IsMember[3] == true {
BindRepeater();
}
//if current user is a manager and named in level1, 2 or 3, load grid
else if ((strLevel1 == strCurrentUser && IsMember[1] == true) ||
(strLevel2 == strCurrentUser && IsMember[1] == true) ||
(strLevel3 == strCurrentUser && IsMember[1] == true))
{
//Example of error log that throws HTTP 401 error when uncommented
//oErrorLog.WriteErrorLog("(strCurrentUser=" + strCurrentUser + ") History Log: Line398-401_AuthorizeCurrentUserSelection(" + eID + ", supUserName=" + supUserName + "). Level1=" + strLevel1 + ", Level2=" + strLevel2 + ", Level3=" + strLevel3 + ", IsMember[1]=true ");
//hide Lock/Unlock buttons
Panel1.Visible = false;
//show grid
BindRepeater();
}
else
{
//redirect
Response.Redirect("~/Warning/AccessDenied.aspx");
}//end if/else
}//end try
catch (SqlException ex)
{
oErrorLog.WriteErrorLog("(" + strCurrentUser + ")SqlException in ReviewForm_AuthorizeCurrentUserSelection(): " + ex.ToString());
} //end catch
}
答案 0 :(得分:0)
我的NA和我想出了问题所在。用于检索当前用户的代码是System.Environment.UserName
,它检索AD属性中的2000之前的显示名称,例如,“SManager
”而不是“smanager
”。允许访问应用页面2的比较必须为小写,因此在这种情况下,SPmanager
与3个评论者列表中的smanager
不匹配。
解决方案是更改AD中的2000之前的用户名,其中UpperCase首字母曾经被用于所有小写,现在自动完成,在较新版本的AD中。
我有点不知道MSDN没有准确指出,它在哪里检索Username属性。