博客地址 http://blog.csdn.net/foxdave
SharePoint 2010 表单认证,基于现有数据库的用户信息表
本文主要描述本人配置过程中涉及到的步骤,仅作为参考,不要仅限于此步骤。
另外本文通俗易懂,适合大众口味儿。
I. 开启并配置基于声明的身份验证
打开SharePoint 2010 Management Shell,依次执行以下语句
$app = Get-SPWebApplication "<your webapp url>"
$app.UseClaimsAuthentication = "true"
$app.Update()
进入管理中心->应用程序管理->管理Web应用程序,选中上面的webapp,点击身份验证提供程序,点击默认链接弹出验证配置窗口。
勾选“启用基于窗体的身份验证(FBA)”,填入名称,这里用mp和rp举例,之后会用到;登录页URL这里,可以默认也可以自定义,这里我选择了自定义,是自己写的一个登录页。
点击保存完成第一步骤。
II. WebConfig配置
需要配置mp和rp的位置有三个,分别是管理中心、webapp端口对应的IIS目录,以及{SharePoint Root}\WebServices\SecurityToken目录下的web.config文件
需要添加的内容如下
<membership defaultProvider="i">
<providers>
<!--将以下节点添加到指定位置-->
<add name="mp" type="<assembly>" />
</providers>
</membership>
<roleManager defaultProvider="c" enabled="true" cacheRolesInCookie="false">
<providers>
<!--将以下节点添加到指定位置-->
<add name="rp" type="<assembly>" />
</providers>
</roleManager>
<connectionStrings>
<add connectionString="<connStr>" name="Conn" />
</connectionStrings>
其中assembly为自定义Provider的dll的描述,后面会提到;connStr为数据库连接串。
III. 自定义MembershipProvider
大致的思路是写两个sealed类,mp继承MembershipProvider,rp继承RoleProvider,我的环境中没有用到角色,所以rp只做了继承,注释掉了
rp代码
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Web.Security;
namespace Providers
{
public sealed class rp : RoleProvider
{
private bool mWriteExceptionsToEventLog = false;
public bool WriteExceptionsToEventLog
{
get
{
return mWriteExceptionsToEventLog;
}
set
{
mWriteExceptionsToEventLog = value;
}
}
public override void Initialize(string name, NameValueCollection config)
{
base.Initialize(name, config);
}
private string pApplicationName = "";
public override string ApplicationName
{
get
{
return pApplicationName;
}
set
{
pApplicationName = value;
}
}
public override void AddUsersToRoles(string[] usernames, string[] rolenames)
{
throw new NotImplementedException();
}
public override void CreateRole(string rolename)
{
throw new NotImplementedException();
}
public override bool DeleteRole(string rolename, bool throwOnPopulatedRole)
{
throw new NotImplementedException();
}
public override string[] GetAllRoles()
{
return null;
}
public override string[] GetRolesForUser(string username)
{
return null;
}
public override string[] GetUsersInRole(string rolename)
{
return null;
}
public override bool IsUserInRole(string username, string rolename)
{
return false;
}
public override void RemoveUsersFromRoles(string[] usernames, string[] rolenames)
{
throw new NotImplementedException();
}
public override bool RoleExists(string rolename)
{
return false;
}
public override string[] FindUsersInRole(string rolename, string usernameToMatch)
{
return null;
}
private static List<string> GetAllUsers()
{
return null;
}
private static List<string> FindAllRoles()
{
return null;
}
private List<string> FindRolesForUser(string username)
{
return null;
}
}
}
mp最少实现以下四个方法,完成在SharePoint上查找添加用户以及登录逻辑的自定义处理。
GetAllUsers、GetUser、ValidateUser、FindUsersByName
我这里大致的做法就是用Webconfig中添加的数据库连接串去操作现有数据库的用户表,尝试用Entities但是好像行不通
mp核心代码
public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
{
MembershipUserCollection spusers = new MembershipUserCollection();
List<MIPUser> users = GetAllUsers();
foreach (MIPUser user in spusers)
{
MembershipUser spuser = new MembershipUser(this.Name,
user.LoginName,
user.LoginName,
user.LoginName + "@contoso.com",
"",
"",
true,
false,
DateTime.Today,
DateTime.Today,
DateTime.Today,
DateTime.Today,
DateTime.Today);
spusers.Add(spuser);
}
totalRecords = spusers.Count;
return spusers;
}
public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
{
MembershipUser spuser = null;
List<MIPUser> users = GetAllUsers();
var query = users.Where(u => u.LoginName.IndexOf(providerUserKey.ToString(), StringComparison.CurrentCultureIgnoreCase) >= 0 ||
u.DisplayName.IndexOf(providerUserKey.ToString(), StringComparison.CurrentCultureIgnoreCase) >= 0).Select(u => u);
if (query.Count() != 0)
{
var user = query.First();
spuser = new MembershipUser(this.Name,
user.LoginName,
user.LoginName,
user.LoginName + "@contoso.com",
"",
"",
true,
false,
DateTime.Today,
DateTime.Today,
DateTime.Today,
DateTime.Today,
DateTime.Today);
return spuser;
}
else
{
return null;
}
}
public override MembershipUser GetUser(string username, bool userIsOnline)
{
MembershipUser spuser = null;
List<MIPUser> users = GetAllUsers();
var query = users.Where(u => u.LoginName.Equals(username, StringComparison.CurrentCultureIgnoreCase) ||
u.DisplayName.Equals(username, StringComparison.CurrentCultureIgnoreCase)).Select(u => u);
if (query.Count() != 0)
{
var user = query.First();
spuser = new MembershipUser(this.Name,
user.LoginName,
user.LoginName,
user.LoginName + "@contoso.com",
"",
"",
true,
false,
DateTime.Today,
DateTime.Today,
DateTime.Today,
DateTime.Today,
DateTime.Today);
return spuser;
}
else
{
return null;
}
}
public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
{
MembershipUserCollection spusers = new MembershipUserCollection();
List<MIPUser> users = GetAllUsers();
var query = users.Where(u => u.LoginName.IndexOf(usernameToMatch, StringComparison.CurrentCultureIgnoreCase) >= 0 ||
u.DisplayName.IndexOf(usernameToMatch, StringComparison.CurrentCultureIgnoreCase) >= 0).Select(name => name);
foreach (var user in query)
{
MembershipUser spuser = new MembershipUser(this.Name,
user.LoginName,
user.LoginName,
user.LoginName + "@contoso.com",
"",
"",
true,
false,
DateTime.Today,
DateTime.Today,
DateTime.Today,
DateTime.Today,
DateTime.Today);
spusers.Add(spuser);
}
totalRecords = query.Count();
return spusers;
}
写好后将dll添加强命名,部署到GAC。
IV. 番外-自定义登录页
自定义登录页,没什么难度,直接贴代码了
ASPX
<%@ Assembly Name="$SharePoint.Project.AssemblyFullName$" %>
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="login.aspx.cs" Inherits="Authentication.login" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<script language="javascript" for="document" event="onkeydown">
if (event.keyCode == 13) {
document.getElementById("<%=btnLogin.ClientID %>").click();
}
</script>
<script language="javascript" type="text/javascript">
function login() {
if (document.getElementById("<%=txtUserName.ClientID %>").value == "") {
alert('请输入用户名');
return;
}
if (document.getElementById("<%=txtPassword.ClientID %>").value == "") {
alert('请输入密码');
return;
}
document.getElementById("<%=btnLogin.ClientID %>").click();
}
</script>
</head>
<body>
<form action="" id="form" runat="server">
<table border="0" cellspacing="0" cellpadding="0" class="login_table">
<tr>
<td class="login_td" align="center">
<div class="logan_contai">
<div class="login_box" style="height: 488px;">
<div class="login_top">
<div class="login_top_wel">
欢迎使用</div>
<div class="login_top_nav">
</div>
</div>
<div class="login_main png">
<asp:Literal ID="ltError" runat="server"></asp:Literal>
<div class="login_txt_box">
<ul>
<li>
<div class="login_name">
用户名</div>
<div class="login_inpbox">
<asp:TextBox ID="txtUserName" runat="server" CssClass="login_input" οnfοcus="this.className='login_input_hov'"
MaxLength="100" οnblur="this.className='login_input'"></asp:TextBox>
<div class="login_wrong">
</div>
</div>
</li>
<li>
<div class="login_name">
密 码</div>
<div class="login_inpbox">
<asp:TextBox ID="txtPassword" runat="server" TextMode="Password" CssClass="login_input"
οnfοcus="this.className='login_input_hov'" MaxLength="100" οnblur="this.className='login_input'"></asp:TextBox>
</div>
<div class="login_wrong">
</div>
</li>
<li>
<div class="login_btn" style="width: 191px; padding: 9px 0 0 155px;">
<a href="#" title="" οnclick="login()">登 录</a></div>
<div style="display: none;">
<asp:Button CssClass="login_btn" Width="191px" ID="btnLogin" runat="server" Text="登录"
OnClick="btnLogin_Click" Style="padding: 9px 0 0 155px" />
</div>
</li>
</ul>
</div>
</div>
<div class="login_foot png">
</div>
</div>
</div>
</td>
</tr>
</table>
</form>
</body>
</html>
CS
using System;
using System.Web.UI;
using Microsoft.SharePoint.IdentityModel;
namespace Authentication
{
public partial class login : Page
{
protected void Page_Load(object sender, EventArgs e) { }
protected void btnLogin_Click(object sender, EventArgs e)
{
Login(this.txtUserName.Text, this.txtPassword.Text);
}
private void Login(string username, string passwrod)
{
try
{
bool status = SPClaimsUtility.AuthenticateFormsUser(Request.Url, username, passwrod);
if (!status)
{
ltError.Text = "用户名或密码错误,请重新输入!";
}
else
{
if (Request.QueryString["ReturnUrl"] != null && Request.QueryString["ReturnUrl"] != "")
{
Response.Redirect(Request.QueryString["ReturnUrl"]);
}
else if (Request.QueryString["Source"] != null && Request.QueryString["Source"] != "")
{
Response.Redirect(Request.QueryString["Source"]);
}
else
{
Response.Redirect("~/");
}
}
}
catch (Exception ex)
{
ltError.Text = "系统错误:<br />";
ltError.Text = ex.Message;
}
}
}
}
以上就是大致的步骤。PS:在搜索添加SharePoint用户的时候,无法显示成名称,只能显示登录名,还不知道如何解决。