ASP.NET 身份教程 II:(用户管理 3)用户登录和电子邮件验证功能
三.用户登录
当用户在你的网站上完成注册之后,下次再光顾你的网站时,只需要登录一下即可,登录时需要提供帐号和密码。还有在用户注册时,如果注册成功,也需要执行一下登录操作,在 7.1 节的注册用户逻辑中,没有实现登录操作,在本节中会完成登录操作。登录成功后,会在顶部导航栏上显示用户的帐号和注销按钮,表示当前用户已经登录该网站.
在 ASP.NET Identity 中,使用登录 API 就可以轻松的完成登录,不需要我们编写任何额外的登录逻辑代码,包括用户在客户端 Cookies 中的存储,都是由 ASP.NETIdentity 来完成的。
3.2. 继承 SignInManager<User, string>
在 ASP.NET Identity 中实现用户登录,需要配置应用程序登录管理器。应用程序登录管理器是继承了 SignInManager<User, string>的类来完成的。
在“App_Start”文件夹中的“IdentityConfig.cs”文件中的“Yidosoft.Identity”名称空间下编写如下代码::
/// <summary> /// 配置应用程序登录管理器 /// </summary> public class SignInManager : SignInManager<User, string> { public SignInManager(UserManager userManager, IAuthenticationManager authenticationManager) : base(userManager, authenticationManager) { } public override Task<ClaimsIdentity> CreateUserIdentityAsync(User user) { return user.GenerateUserIdentityAsync((UserManager)UserManager); } public static SignInManager Create(IdentityFactoryOptions<SignInManager> options, IOwinContext context) { return new SignInManager(context.GetUserManager<UserManager>(), context.Authentication); } }
其实这个内容是一开始就在前面教程中进行了使用。
然后再在“Models”文件夹中打开“User.cs”文件,并在 User 类中添加如下方法,其实上次已加入了。
public class User: IdentityUser { public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<User> manager) { // 请注意,authenticationType 必须与 CookieAuthenticationOptions.AuthenticationType 中定义的相应项匹配 var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie); // 在此处添加自定义用户声明 return userIdentity; } #region 添加字段 [Display(Name = "微信")] public virtual string WX { get; set; }
在此代码可以看出,ASP.NET Identity 是完全支持基于声明的身份验证的
.3. 注册 SignInManager
配置好的应用程序登录管理器,还需要在“Startup”类中注册一下,打开“App_Start”文件夹下的“Startup.Auth.cs”文件,然后添加如下代码:
app.CreatePerOwinContext<SignInManager>(SignInManager.Create);
4..4. 编写 LoginViewModel
在“ViewModels”文件夹中添加一个名称为“LoginViewModel”的类,然后编写如下代码:因为我使用的userName登录,所以我声明的字段没有Email,而“RememberMe”属性是一个bool 类型,用于让用户选择是否在本地记住账号和密码信息。
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Web; namespace jsdhh2.ViewModels { public class LoginViewModel { [Required] [Display(Name = "用户名")] public string UserName { get; set; } [Required] [DataType(DataType.Password)] [Display(Name = "密码")] public string Password { get; set; } [Display(Name = "记住我?")] public bool RememberMe { get; set; } } }
.5. 编写 Login 方法
在“UserController”控制器中编写一个带有 HttpGet 特性的 Login()方法,用于呈现用户填写登录账户和密码的页面。再编写一个带有 HttpPost 特性的 Login()方法,用于将用户填写的账户和密码提交到服务器进行验证。代码如下:
private SignInManager _signInManager; public SignInManager SignInManager { get { return _signInManager ?? HttpContext.GetOwinContext().Get<SignInManager>(); } private set { _signInManager = value; } }
private ActionResult RedirectToLocal(string returnUrl) { if (Url.IsLocalUrl(returnUrl)) { return Redirect(returnUrl); } return RedirectToAction("Index", "Home"); } }
SignInManager 属性用于获取当前的应用程序登录管理器,然后就可以使用与登录相关的方法或属性。RedirectToLocal()方法用于完成某个某个操作后进行跳转,如果存在返回的 Url,则跳转到返回 Url,如果没有,则跳转到 Home 控制器的 Index()方法上。
/// <summary> /// 登录 /// </summary> /// <param name="returnUrl"></param> /// <returns></returns> [HttpGet] [AllowAnonymous] public ActionResult Login(string returnUrl) { ViewBag.ReturnUrl = returnUrl; return View(); } /// <summary> /// 登录 /// </summary> /// <param name="model"></param> /// <param name="returnUrl"></param> /// <returns></returns> [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task<ActionResult> Login(jsdhh2.ViewModels.LoginViewModel model, string returnUrl) { if (!ModelState.IsValid) { return View(model); } // 这不会计入到为执行帐户锁定而统计的登录失败次数中 // 若要在多次输入错误密码的情况下触发帐户锁定,请更改为 shouldLockout: true var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: false); switch (result) { case SignInStatus.Success: return RedirectToLocal(returnUrl); case SignInStatus.LockedOut: return View("Lockout"); case SignInStatus.RequiresVerification: return RedirectToAction("SendCode", new { ReturnUrl = returnUrl, RememberMe = model.RememberMe }); case SignInStatus.Failure: default: ModelState.AddModelError("", "无效的登录尝试。"); return View(model); } }
同时还有个新方法
private ActionResult RedirectToLocal(string returnUrl) { if (Url.IsLocalUrl(returnUrl)) { return Redirect(returnUrl); } return RedirectToAction("Index", "Home"); } }
在 HttpPost 的 Login()方法中,如果登录成功,则转到返回 Url,如果用户已锁定,则返回到”Lockout”视图,如果用户未完成验证(邮箱手机验证或双重验证),则转到“SendCode”方法。其它情况,则添加登录失败的错误信息。
6. 编写 Login 视图
“Views”“User”文件夹中添加一个名称为“Login”的视图,并编写如下代码:
@using jsdhh2.Models @model jsdhh2.ViewModels.LoginViewModel @{ ViewBag.Title = "登录"; } <div class="row"> <div class="col-md-8"> <section id="loginForm"> @using (Html.BeginForm("Login", "User", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" })) { @Html.AntiForgeryToken() <h4>@ViewBag.Title。</h4> <hr /> @Html.ValidationSummary(true, "", new { @class = "text-danger" }) <div class="form-group"> @Html.LabelFor(m => m.UserName, new { @class = "col-md-2 control-label" }) <div class="col-md-10"> @Html.TextBoxFor(m => m.UserName, new { @class = "form-control" }) @Html.ValidationMessageFor(m => m.UserName, "", new { @class = "text-danger" }) </div> </div> <div class="form-group"> @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" }) <div class="col-md-10"> @Html.PasswordFor(m => m.Password, new { @class = "form-control" }) @Html.ValidationMessageFor(m => m.Password, "", new { @class = "text-danger" }) </div> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <div class="checkbox"> @Html.CheckBoxFor(m => m.RememberMe) @Html.LabelFor(m => m.RememberMe) </div> </div> </div> <div class="form-group"> <div class="col-md-offset-2 col-md-10"> <input type="submit" value="登录" class="btn btn-default" /> </div> </div> <p> @Html.ActionLink("注册为新用户", "Add") </p> @* 在为密码重置功能启用帐户确认后启用此项 <p> @Html.ActionLink("忘记了密码?", "ForgotPassword") </p>*@ } </section> </div> </div>
7.登录样式
输入用户名,秘码登录
图 7-23 上看,是转到了网站的首页,这个首页在“RouteConfig.cs“中默认配置好的。如下代码
namespace Yidosoft.Identity { public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } } }
在此代码中,配置的默认首页就是 Home 控制器下的 Index()方法,默认的首页地址,在浏览器的地址中,控制器和方法名都是可以省略的。所以图 7-23 转向的地址就是” htttp://localhost:6460/Home/Index”,只是省略了而已。在登录逻辑代码中,转向了 Home/Index,表示用户登录成功了。
8.创建首大页
因为我们是用MVC项目first code,所以home的index视图是自动生成的。
我们主要是编写“_LoginPartial.cshtml“视图。用于呈现用户的登录信息。由于网站的顶部导航视图代码是编写在“Views”\“Shared”文件夹下的“_Layout.cshtml”布局视图中的。所以我们也将“_LoginPartial.cshtml”放在“Views”/“Shared”文件夹下。
@using Microsoft.AspNet.Identity @if (Request.IsAuthenticated) { using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" })) { @Html.AntiForgeryToken() <ul class="nav navbar-nav navbar-right"> <li> @Html.ActionLink("你好," + User.Identity.GetUserName() + "!", "Index", "Manage", routeValues: null, htmlAttributes: new { title = "Manage" }) </li> <li><a href="javascript:document.getElementById('logoutForm').submit()">注销</a></li> </ul> } } else { <ul class="nav navbar-nav navbar-right"> <li>@Html.ActionLink("注册", "Register", "Account", routeValues: null, htmlAttributes: new { id = "registerLink" })</li> <li>@Html.ActionLink("登录", "Login", "Account", routeValues: null, htmlAttributes: new { id = "loginLink" })</li> </ul> }
然后打开“_Layout.cshtml”,将“_LoginPartial.cshtml”以部分视图的形式嵌入。如图7-26 所示:
@Html.Partial("_LoginPartial")
代码,将部分视图嵌入到布局视图中。现在运行一下首页。
的顶部导航栏上,是不是已经看到在前面登录的账户名了,并且还有注销按钮,注销按钮的功能后面会讲解
5. 确认用户
确认用户是指当用户在网站中注册成功之后,会通过邮件或手机发送一个验证码,然后通过这个验证码来确认用户的正确性。这里主要讲解使用电子邮件来确认用户,使用 163 邮箱的网关来发送确认用户的
电子邮件。
5.1. 配置 EmailService
配置 EmailService 服务,需要继承 IidentityMessageService 接口,实现 SendAsync()方法来发送邮件。在“App_Start”文件夹下的“IdentityConfig.cs”文件中的“Yidosoft.Identity”名称空间
下编写如下代码:
public class EmailService : IIdentityMessageService { public Task SendAsync(IdentityMessage message) { //编写发送邮件的代码 Common.SendMail("smtp.126.com", 25, "lbj$4561200", "yidosoft@126.com", message.Destination, message.Subject, message.Body); return Task.FromResult(0); } }
在 SendAsync()方法中就可以编写发送电子邮件的代码。这里使用了 Common 类中的静态方法 SendMail()来发送邮件,使用的是 smtp.126.com 来发送邮件。在“Yidosoft.Identity”的根目录下添加一个 Common 类文件,然后编写如下代码
using System.Net; using System.Net.Mail; namespace jsdhh2 { public class Common { public static bool SendMail(string strSmtpServer, int iSmtpPort, string Password, string strFrom, string strto, string strSubject, string strBody) { //设置发件人信箱,及显示名字 MailAddress mailFrom = new MailAddress(strFrom); //设置收件人信箱,及显示名字 MailAddress mailTo = new MailAddress(strto); //创建一个MailMessage对象 MailMessage oMail = new MailMessage(mailFrom, mailTo); oMail.Subject = strSubject; oMail.Body = strBody; oMail.IsBodyHtml = true; //指定邮件格式,支持HTML格式 oMail.BodyEncoding = System.Text.Encoding.GetEncoding("GB2312");//邮件采用的编码 oMail.SubjectEncoding = System.Text.Encoding.GetEncoding("GB2312");//邮件采用的编码 oMail.Priority = MailPriority.High;//设置邮件的优先级为高 //发送邮件服务器 SmtpClient client = new SmtpClient(); //发送邮件服务器的smtp //每种邮箱都不一致 client.Host = strSmtpServer; //指定邮件服务器 //发送邮件服务器端口 client.Port = iSmtpPort; //设置超时时间 client.Timeout = 9999; //设置为发送认证消息 client.UseDefaultCredentials = true; //指定服务器邮件,及密码 //发邮件人的邮箱地址和密码 client.Credentials = new NetworkCredential(strFrom, Password); client.Send(oMail); //发送邮件 //释放资源 mailFrom = null; mailTo = null; client.Dispose();//释放资源 oMail.Dispose(); //释放资源 return true; } } }
然后在IdentityConfig.CS中的“UserManager”类中的“Create()”方法中添加如下代码:
/// <summary> /// 配置用户管理器 /// </summary> public class UserManager : UserManager<User> { public UserManager(IUserStore<User> store) : base(store) { } public static UserManager Create(IdentityFactoryOptions<UserManager> options, IOwinContext context) { var manager = new UserManager(new UserStore<User>(context.Get<Models.IdentityDbContext>())); manager.EmailService = new EmailService(); var dataProtectionProvider = options.DataProtectionProvider; if (dataProtectionProvider != null) { manager.UserTokenProvider = new DataProtectorTokenProvider<User>(dataProtectionProvider.Create("EmailConfirmation")); } return manager; } }
.5.2. 发送确认用户邮件
带 HttpPost 的 Add()方法中添加发送确认用户的邮件,表示在用户注册后需要验证一下。
打开“UserController.cs”文件,找到带有 HttpPost 特性的 Add()方法。原来的代码如下:
HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task<ActionResult> Add(AddUserViewModel addUserModel) { if (ModelState.IsValid) { var user = new User { UserName = addUserModel.Email, Email = addUserModel.Email, QQNumber = addUserModel.QQNumber, WechatNumber = addUserModel.WechatNumber }; var result = await UserManager.CreateAsync(user, addUserModel.Password); if (result.Succeeded) { return RedirectToAction("List", "User"); } AddErrors(result); } return View(addUserModel); }
现在修改一下,添加用户登录和发送确认用户电子邮件的代码,如下:
[HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task<ActionResult> Add(AddUserViewModel addUserModel) { if (ModelState.IsValid) { var user = new User { UserName = addUserModel.Email, Email = addUserModel.Email, QQNumber = addUserModel.QQNumber, WechatNumber = addUserModel.WechatNumber }; var result = await UserManager.CreateAsync(user, addUserModel.Password); if (result.Succeeded) { //登录 await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false); // 发送包含此链接的电子邮件 string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id); var callbackUrl = Url.Action("ConfirmEmail", "User", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme); await UserManager.SendEmailAsync(user.Id, "确认你的帐户", "请通过单击 <a href=\"" + callbackUrl + "\">这里</a>来确认你的帐户"); //return RedirectToAction("List", "User"); return RedirectToAction("Index", "Home"); } AddErrors(result); } return View(addUserModel); }
在此代码中,使用 UserManager.GenerateEmailConfirmationTokenAsync()方法,根据 User.Id 一成一个 Code,然后附加到验证 Url 中。最后使用 UserManager.SendEmailAsync()来发送电子邮件。
5.3. 接收电子邮件:在这要说明,我这没有成功,是因为一是我使用的USERNAME,而非Email,同时我未正确配置邮箱端口。
现在新注册一个用户,使用真实的电子邮件,然后接收该电子邮件,并完成邮件验证。
先按真实的EMAIL地址注册,并登录。再到邮箱中去查看是否有邮箱。
然后登录邮箱
正确转到首页了,并且显示了当前注册的用户信息,表示登录成功了。现在登录注册的邮件,看是否能接收到邮件。如图 7-30 所示:
中已经接收到邮件了,点击“这里”链接去确认账户。如图 7-31 所示
由于我们还没有编写邮件验证的代码,所以图 7-31 的页面是不存在的
.5.4. 邮箱验证
在“UserController”控制器中添加一个名称为“ConfirmEmail()”的方法。代码如下:
/// <summary> /// 邮箱验证 /// </summary> /// <param name="userId"></param> /// <param name="code"></param> /// <returns></returns> [HttpGet] [AllowAnonymous] public async Task<ActionResult> ConfirmEmail(string userId, string code) { if (userId == null || code == null) { return View("Error"); } var result = await UserManager.ConfirmEmailAsync(userId, code); return View(result.Succeeded ? "ConfirmEmail" : "Error"); }
ConfirmEmail()方法需要接收到 2 个参数,1 个是 userId,1 个是 code,与图 7-31浏览器中的 Url 参数是相对应的。
在数据库中存储的用户信息表是 AspNetUsers,有一个字段是“EmailConfirmed”,是 bit 类型,未验证时,该字段的值为 false,验证通过后,修改后 true。如图 7-32
在 ConfirmEmail()方法中用到了“Error”和“ConfirmEmail”这两个视图,在“Views”“User”中添加“ConfirmEmail.cshtml”视图,并编写如下代码:
@{ ViewBag.Title = "确认电子邮件"; } <h2>@ViewBag.Title。</h2> <div> <p> 感谢你确认电子邮件。请 @Html.ActionLink("单击此处登录", "Login", "Account", routeValues: null, htmlAttributes: new { id = "loginLink" }) </p> </div>
在“Shared”文件夹中添加“Error.cshtml”视图,并编写如下代码:这个基本是自带的
@model System.Web.Mvc.HandleErrorInfo @{ ViewBag.Title = "Error"; } <h1 class="text-danger">Error.</h1> <h2 class="text-danger">An error occurred while processing your request.</h2>
好了,现在重新运行图 7-31 的页面,如图 7-33 所示
图 7-33 提示已经确认了电子邮件,可以正常登录了。那么我们回到数据库看一下,如图 7-34 所示:
在图 7-34 中,“EmailConfirmed”字段的值已经变为“True”了,表示该用户的电子邮
件已经验证过了
推荐阅读
-
ASP.NET 身份教程 II:(用户管理 3)用户登录和电子邮件验证功能
-
41 个下载免费 3D 模型的最佳网站-使用说明:使用权限可能因型号而异。因此,在下载文件之前,请仔细检查每个下载页面上的许可证和使用权限。 17. Clara.io Clara.io 是一个创建 3D 内容的全球平台,也是一个培养新 3D 艺术家的社区。Clara.io 提供+100,000个免费的3D模型,包括OBJ,Blend,STL,FBX,DAE,Babylon.JS,Three.JS格式,用于 Clara.io,Unity 3D,Blender,Sketchup,Cinema 4D,3DS Max和Maya。 使用说明:免费,标准和专业帐户仅供个人使用,如果您需要将 clara.io 用于商业用途,请与销售团队联系。 18. 3DExport 3DExport是一个市场,您可以在其中购买和销售用于CG项目的3D模型,3D打印模型和纹理。它提供15 +不同的3D格式供下载,如3DS MAX(.max),Cinema4D(.c4d),Maya(.mb,.ma),Lightwave(.lwo),Softimage(.xsi),Wavefront OBJ(.obj),Autodesk FBX(.fbx)等。它还提供15种不同的语言! 使用说明:免费下载仅供个人和非商业用途。 19. 3D Warehouse 3D Warehouse是一个开放的库,允许用户共享和下载SketchUp 3D模型,用于建筑,设计,施工和娱乐!任何人都可以免费制作,修改和重新上传内容到3D仓库,您可以找到任何您能想到的东西,如家具,电子产品,室内产品等。 使用说明:3D Warehouse中的所有模型都是免费的,因此任何人都可以下载文件以用于SketchUp甚至其他软件,如AutoCAD,Revit和ArchiCAD。 20. CadNav.com CadNav是CGI平面设计师和CAD / CAM / CAE工程师的在线3D模型库,我们提供超过50000 +免费3D模型和CAD模型下载。在CadNav网站上,您可以下载高质量的多边形网格3D模型,3D CAD实体对象,纹理,Vray材料,3D作品,CAD图纸等。 使用说明:免费下载仅供个人和非商业用途。 21. All3dfree.net 就像网站名称一样,它提供免费的3D模型,还包括Vray材料,CAD块,2d和3d纹理集合,无需注册即可免费下载。它是不断更新的,因此您可以查找或请求3DS,MAX,C4D,skp,OBJ,FBX,MTL等格式的模型。 使用说明:所有资源均不允许用于商业用途,否则您将承担责任。 22. Hum3D 自2005年以来,Hum3D帮助来自3多个国家的80D艺术家节省3D建模时间,并制作逼真的3D模型,用于电影,视频游戏,AR应用程序和可视化。所有模型均由首席3D艺术家进行验证,他们检查其是否符合专业要求和最新的3D建模标准。 使用说明:免费下载仅供个人和非商业用途。 23. Artist-3D.com 艺术家-3D 库存的免费 3D 模型下载按通用类别排序。它为人体解剖学、汽车、家具、火箭、卫星等模型提供 AutoDesk 3DS Max 格式。您还可以在浏览他们的网站时找到教程和类似类型的建模。 使用说明:使用权限可能因型号而异。因此,在下载文件之前,请仔细检查每个下载页面上的许可证和使用权限。 24. Free the models 就像本网站的标题一样,它为3d应用程序和3d游戏引擎提供免费的内容模型。您可以为您的任何项目找到许多有趣且有用的模型!它提供3ds,wavefront,bryce,poser,lightwave,md2和unity3d格式的模型。还有一个很棒的纹理集合,可以在您最喜欢的建模和渲染程序中使用。 使用说明:您从这里下载的所有内容都可以免费使用,除非它不能包含在另一个免费的网络或CD收藏中,也不能单独出售。否则,您可以在商业游戏,3D应用程序或渲染作品中使用它。您不必提供信用,但如果您这样做,那就太好了。 25. Resources.blogscopia 本网站由一家名为Scopia的公司创建。他们制作3D图像和视频,您可以找到许多为CGI工作的信息架构设计的模型,所有这些都可以在现实生活中使用。您可以免费下载它们,但是,如果您想一次下载它们,您可以支付 3 到 9 欧元。 使用说明:您可以免费下载模型部分的所有文件。每个压缩文件都包含您也可以在此处找到的许可证。基本上,您可以对文件执行任何操作。唯一的限制是不归属于Scopia的重新分发。 26.ambientCG 1000+公共领域PBR材料适合所有人!环境CG是使用许多不同的方法和资产类型创建的,例如照片纹理(PBR),贴花(PBR),图集(PBR),照片纹理(普通),物质存档(SBSAR),雕刻画笔,3D模型和地形。您可以在所有项目中*使用它们! 使用说明:在 ambientCG 上提供下载的所有 PBR 材料、画笔、照片和 3D 模型均根据知识共享 CC0 1.0 通用许可提供。您可以复制、修改、分发和执行作品,即使是出于商业目的,也无需征得许可。信用将不胜感激。 不要满足于平庸的大理石纹理 - 立即使用我们的免费PBR大理石纹理升级您的3D设计。 27.Pixar One Twenty Eight 这是一个提供官方动画行业经典纹理的网站:皮克斯,创建于 1993 年,该纹理库包括 128 个重复纹理,现在免费提供。 它包含您来到的纹理,包括砖块和动物毛皮。肯定会有一些你可以使用的东西。 使用说明:皮克斯动画工作室的《Pixar One Twenty Eight》根据知识共享署名4.0国际许可协议进行许可。即使出于商业目的,您也可以重新混合、调整和构建您的作品,只要您以相同的条款对新创作进行信用和许可。 访问数以千计的免费纹理并提升您的设计游戏 - 立即开始下载! 28. 3DXO 即使有近 620 个免费贴纸可供下载,3DXO 也不是最大的资源,但它的内容非常有用,不需要注册。无论是简单的墙壁或地板,还是一些奇怪的小东西,您都需要的纹理都可以在此网站上看到。 使用说明:使用权限可能因型号而异。因此,在下载文件之前,请仔细检查每个下载页面上的许可证和使用权限。 29. 3DModelsCC0 3DModelsCC0 与其他产品的不同之处在于它包含超过 250+ 个高质量 3D 模型,并且本网站上的所有内容都是免费的,完全是公共领域!使用我们的模型时无需信用或归属! 使用说明:为每个人提供完全免费的公共领域内容。 30.Sketch up texture club Sketchup Texture Club是一个非营利性的教育和信息门户网站,由3D社区的图像促进协会管理,特别强调面向学生和建筑和室内设计专业人士的可视化和渲染技术,以及所有正在学习3D可视化的人。 使用说明:您无需支付版税或使用费。纹理可以免费下载和使用。不允许将纹理作为竞争产品出售或重新分发,即使图像被修改也是如此。 31. FlippedNormals FlippedNormal 是一个提供计算机图形和 3D 资产的市场,您可以找到许多用于雕刻、建模、纹理、概念艺术、3D 模型、游戏资产或课程的高级资产! 使用说明:使用权限可能因型号而异。因此,在下载文件之前,请仔细检查每个下载页面上的许可证和使用权限。 32. NASA 3D NASA 3D网站是一个在线门户,提供与太空和各种NASA任务相关的大量三维模型和模拟。该网站是用户友好的,并提供有关每个型号的详细信息。该网站允许用户探索和下载几种不同格式的模型,包括 OBJ、STL 和 FBX,只需单击下载按钮即可。 使用说明: 要下载模型,只需单击模型页面上的下载按钮并选择所需的格式。 33. 3DAGOGO (Astroprint) 3DAGOGO 是一个提供广泛 3D 模型的网站,包括角色、车辆和建筑物。3DAGOGO 的独特功能之一是它专注于适合 3D 打印的模型,使其成为希望创建物理原型或模型的设计师的绝佳资源。要使用 3DAGOGO,设计师只需在网站上搜索他们正在寻找的模型类型,然后下载 STL 格式的文件。 使用说明: 要使用 3DAGOGO,只需搜索所需的 3D 模型类型并下载 STL 格式的文件。根据需要自定义模型,并确保在将其用于商业目的之前检查使用权限。 34. FreeCAD FreeCAD是一款了不起的3D建模软件,可让您在计算机上创建令人难以置信的3D设计。该软件可免费下载和使用,它提供了广泛的工具和功能,可用于创建用于各种目的的3D模型。 该网站易于浏览,您可以找到开始使用FreeCAD的所有必要信息。此外,该网站还提供一系列教程和指南,可帮助您了解 3D 建模的来龙去脉。 使用说明: 要下载模型,请访问网站并从库中选择所需的模型。该网站还提供了一系列使用该软件的教程和指南。 35. Pinshape Pinshape是一个提供一系列3D打印模型的网站。网站上提供的型号质量很高,因此您可以确保您的最终印刷产品看起来很棒。该网站提供了广泛的模型,包括从家居用品到小雕像和珠宝的所有物品。 但这还不是Pinshape所能提供的全部!该网站还允许用户上传和共享自己的3D模型。这意味着您不仅可以下载出色的模型,还可以通过分享自己的设计为社区做出贡献。此外,Pinshape 提供了一系列自定义选项,因此您可以调整和调整模型以满足您的特定需求。 使用说明: 要下载模型,请在网站上创建一个帐户,搜索所需的模型,然后单击下载按钮。该网站还为每种型号提供了一系列定制选项。 36.Yeggi Yeggi 提供了大量免费的 3D 模型,您可以下载各种格式的模型,例如 STL、OBJ 和 FBX。该网站易于使用,您可以按关键字、类别或特定网站搜索模型。 Yeggi 对于任何寻找 3D 模型的人来说都是一个很好的资源。它提供了大量的模型集合,从日常物品到复杂的机械,以及介于两者之间的一切。该网站的收藏量在不断增长,每天都有新的型号增加。 使用说明: 要下载模型,请在网站上搜索所需的模型,然后单击下载按钮。该网站还提供指向托管模型的原始网站的链接。 37. Open3DModel 来自开放3D模型的图像 Open3DModel具有各种类别的模型,包括建筑,车辆和角色。无论您需要建筑物,汽车还是人的3D模型,都可以在此网站上找到。 该网站易于浏览,您可以按类别或关键字搜索模型。每个模型都附带预览图像和详细信息,例如文件格式、大小和多边形数量。此信息可以帮助您选择适合您需求的模型。 使用说明: 要下载模型,请访问网站,从库中选择所需的模型,然后单击下载按钮。 使用最好的 3D 资产管理工具简化您的 3D 制作流程。立即试用它们,将您的 3D 项目提升到一个新的水平! 38. 3DExport 对于那些为其 3D 设计项目寻找 3D 模型、纹理和其他资源的人来说,该平台是一个很好的资源。该网站有大量模型可供选择,包括 3D 打印对象、游戏资产等。用户可以按类别、文件格式或价格范围浏览,以找到适合其项目的完美资源。此外,3DExport 还提供一系列教程和其他 3D 资源,以帮助用户提高技能并创建更令人印象深刻的设计。 使用说明: 要使用 3DExport,只需创建一个帐户并浏览可用型号。您可以按类别、格式和价格进行搜索,以找到所需的型号。找到喜欢的模型后,只需下载它并开始在您的项目中使用它。 39.Blend Swap Blend Swap是一个社区驱动的市场,提供与Blender软件兼容的各种免费3D模型。该平台允许用户共享和下载模型、纹理和其他资产,以便在他们的项目中使用。 使用说明: 创建免费帐户后,您可以浏览社区上传的大量3D模型。当您找到要使用的一个时,只需下载它并将其导入您选择的 3D 软件即可。 40. 3DShook 3DShook 是一个高级 3D 模型市场,提供一系列用于建筑、游戏等各个行业的高质量模型。该平台提供基于订阅的模型,具有不同的定价计划,允许用户访问一系列模型。 使用说明: 注册免费帐户后,只需浏览3D模型库,选择您喜欢的模型,然后以您需要的格式下载它们。 41. Smithsonian X 3D 史密森尼 X 3D 对于正在寻找历史文物和文物的高质量 3D 模型的设计师来说,这是一个独特的资源。该平台提供了大量3D模型,这些模型是根据史密森尼博物馆和研究中心中的真实物体扫描创建的。 使用说明: