如何用工厂实例化一个接口objectfactory
mybatis中的plugin其实就是个interceptor, 它可以拦截Executor 、ParameterHandler 、ResultSetHandler 、StatementHandler 的部分方法,处理我们自己的逻辑。
Executor就是真正执行sql语句的东西, ParameterHandler 是处理我们传入参数的,还记得前面讲TypeHandler的时候提到过,mybatis默认帮我们实现了不少的typeHandler, 当我们不显示配置typeHandler的时候,mybatis会根据参数类型自动选择合适的typeHandler执行,其实就是ParameterHandler 在选择。ResultSetHandler 就是处理返回结果的。
asp.net mvc 统一身份验证问题、怎么实现?
MVC里有AuthorizeAttribute特性,直接标记在Controller类上或者在控制器操作上。
[Authorize]
public class ArticleController : Controller
{
[Authorize]
public ActionResult Index()
{
return View();
}
}
如果用户没有登录,就会跳转到登录页面。也可以自定义扩展AuthorizeAttribute,实现自定义的验证。建议你买本书看,一两句话说不清楚。
用web api 分离前后台 会不会有风险
1、 OAuth是做什么的?
在网上浏览时,大家都见过这样的功能:网站A提供了第三方登录服务,比如使用新浪微博、QQ账户登录。用户使用第三方账户登陆后,第三方返回Token给网站A,当网站A调用第三方服务请求登录用户信息时需传递该Token给第三方,第三方才允许该服务请求。之后的每次请求无需再次认证,直接使用该Token即可。这就是OAuth的典型应用。
2、 简单使用介绍 (具体使用OAuth的方法请参考:在ASP.NET中基于Owin OAuth使用Client Credentials Grant授权发放Token)
2.1、用户登录的过程即是获取Token的过程,前端用户登录示例代码如下:
1 $.ajax({
2 type: "POST",
3 url: api_address + "token", //api_address为WebApi服务地址,由于OAuth的使用中设置了属性TokenEndpointPath = new PathString("/token"),所以请求到“token”链接时即可自动进入认证流程。
4 data: { grant_type: "password", username: username, password: password, ran: Math.random() },//传递用户名、密码、认证方式
5 dataType: "json",
6 success: function (result) {
7 if (result.access_token && result.access_token.length > 0) {
8 //result.access_token即是有效的服务调用凭证,可以把该值存入到Cookie中,以备下次使用。
9 callback(1, "登录成功。");
10 }
11 else {
12 callback(0, "未知错误!");
13 }
14 },
15 error: function (XMLHttpRequest, textStatus, errorThrown) {
16 callback(0, XMLHttpRequest.responseJSON.error);
17 }
18 });
登录代码
2.2、当认证方式为password时,已下方法为认证流程中的一步。(认证通过才会返回Token)
1 public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
2 {
3 var username= context.UserName;
4 var password=context.Password;
5 if(用户名与密码不合法)
6 {
7 context.setError(“用户名或密码错误!”);//认证不通过
8 }
9 else
10 {
11 var oAuthIdentity = new ClaimsIdentity(context.Options.AuthenticationType);
12 oAuthIdentity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
13 //可以加入用户信息及其他必要信息到Token中,以便在api服务中使用(使用中HttpContext.Current.User.Identity即为oAuthIdentity对象,WebApi的Controller中可直接使用User.Identity)。
14 oAuthIdentity.AddClaim(new Claim("UserID", user.UserID.ToString()));
15 var ticket = new AuthenticationTicket(oAuthIdentity, new AuthenticationProperties());
16 context.Validated(ticket);//认证通过
17 }
18 return base.GrantResourceOwnerCredentials(context);
19 }
认证代码
3、 已经获取了Token,如何使用?
网上的大部分示例都是使用HttpClient调用的方式,而前后端的完全分离作为一种发展趋势,我们需要Jquery的调用方式。
1 $.ajax({
2 type: “method”,//get,post,put,delete
3 url:api_address + “api/Test”,//如果调用webapi中的TestController
4 data: {data},
5 dataType: "json",
6 headers: {
7 "Authorization": "Bearer " + “token” //把登录获取的Token加入到http请求头中
8 },
9 success: function (result) {
10 callback(result);
11 },
12 error: function (XMLHttpRequest, textStatus, errorThrown) {
13 //。。。。。。
14 }
15 });
调用Api
4、Api的访问权限该如何做?
认证中我们把用户登录成功作为认证通过的标志,但不同角色的用户具有不同的访问权限(个人认为认证中应使用最小权限验证,如示例中的登录成功),如何控制有些Controller不能被低权限用户访问。
1 [Authorize]
2 public class TestController: ApiController
3 {
4 // GET api/
5 public HttpResponseMessage Get(int appid)
6 {
7 return null;
8 }
9 }
一个典型的ApiController
[Authorize]表示访问该Controller的请求必须经过认证(请求头中具有Token信息),这里我们可以自定义一个特性去验证用户权限,并替换特性AuthorizeAttribute。(这里仅提供思路,具体做法请自己摸索,不保证以下代码的正确性)
1 public class CustomeAuthorizeAttribute:System.Web.Http.AuthorizeAttribute
2 {
3 protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext)
4 {
5 if(base.IsAuthorized(actionContext))
6 {
7 //这里对用户的权限进行验证,actionContext可以获得请求的是哪一个Controller
8 var user = HttpContext.Current.User.Identity;//Token中带有的用户信息
9 if (可以访问)
10 {
11 return true;
12 }
13 return false;
14 }
15 return false;
16 }
17 }
18
actionfilterattribute和authorizeattribute有什么区别
1、MVC5只要将属性[Authorize]置于相关的action之前就行,那么在调用Buy action之前,就会运用Authorize过滤器。
2、也可以将属性[Authorize]置于整个Controller之上。这样位于此控制器下的所有action就都运用了此过滤器。
3、也可以将Authorize应用到全部的应用程序的范围类,要使AuthorizeAttribute成为全程序的过滤器,只要将其加入全局过滤器集合RegisterGlobalFilters方法,这个方法位于\App_Start\FilterConfig.cs。
4、如果我们允许部分的控制器或者action允许匿名访问怎么办?只需要在相应的控制器或者action上添加属性[AllowAnonymous]
MVC中施用AuthorizeAttribute做身份验证操作怎么解决
代码顺序为:OnAuthorization-->AuthorizeCore-->HandleUnauthorizedRequest
如果AuthorizeCore返回false时,才会走HandleUnauthorizedRequest 方法,并且Request.StausCode会返回401,401错误又对应了Web.config中
的
所有,AuthorizeCore==false 时,会跳转到 web.config 中定义的 loginUrl="~/"
onauthorization 怎么实现自动执行的
import java.io.BufferedReader;
import java.io.InputStreamReader;
public class test
{
public static void main(String[] args)throws Exception
{
int[] b=new int[200];
int[] c=new int[200];
int i, j;
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String str=null;
用MVC实现登录提示成功跳转
这个简单啊,如下:FMLogin 是表单的验证模型。
public ActionResult Login()
{
return View();
}
[HttpPost]
public ActionResult Login(FMLogin fmd)
{
if(验证失败)
{
Response.Write(一些JS字符串代码,如提示验证失败,跳转等);
Return null;//表示返回一个EmptyResult,表现出来就是一个空白页。
}
Response.Write(一些JS字符串代码,成功后跳转);
Return null;
}
另外可以把输出JS的那些语句封装成一个类,使用方便。还有跳转的JS直接写 一部分就行如
Response.Write("window.location.replace('/Account/Login') ;")
这里建议使用replace,因为它是直接替换当前页的不会在历史记录里留下访问表单验证的这个空白页。
如何实现RESTful Web API的身份验证
最近想拿一个小项目来试水RESTful Web
API,项目只有几个调用,比较简单,但同样需要身份验证,如果是传统的网站的话,那不用说,肯定是用户名+密码在登录页获得登录Token,并把登录
Token记在Cookie和Session中作为身份标识的这种方式,但现在不同了,关键是RESTful,这意味着我们设计出来的这些API是无状态
的(Stateless),下一次的调用请求和这一次的调用请求应该是完全无关的,也就是说,正宗的RESTful Web
API应该是每次调用都应该包含了完整的信息,没错,包括身份信息!
那如何确保安全?传输时给密码做MD5加密?得了吧!这样做只能让你自己感觉“安全”点,其实没什么任何用处,利用现在的技术(有种叫什么Rainbow Table啥的来着?本人外行,不是很懂)很快就能算出明文密码了,而且如何防止挟持和重发攻击?
也许你想到了,SSL,如果你打算采用SSL,请忘记一切自行设计的加密方案,因为SSL已经帮你做好了一切,包括防止监听,防止挟持,防止重发……一切都帮你考虑好了,你大胆地把明文密码写在你的包中就OK了,我向你保证没问题。
但SSL的缺点是服务器端配置相对有点复杂,更关键的就是客户端对此支持可能不好,那你考虑一种自己的加密方法,有木有?我这里提供一种方法,思路来自
于:http://www.thebuzzmedia.com/designing-a-secure-rest-api-without-oauth-
authentication/,我只是把上面的内容中整理了一下变成了我的方法。(传说中的剽窃?呵呵)方法描述如下:
假设有一个用户,用户名是guogangj,密码是123456(呃……这也能叫密码?)
他要GET http://test.com/api/orders/
于是把 http://test.com/api/orders/这个URL和一个新生成的GUID拼在一起,再用123456这个密码执行对称加密,生成的密文为XXXXOOOOXXXXOOOO(假设而已)
数据包中带上用户名guogangj和XXXXOOOOXXXXOOOO这个密文,发送给服务器
服务器收到包后,根据guogangj这个用户名到数据库中查找到123456这个密码
服务器使用123456这个密码来解密XXXXOOOOXXXXOOOO这个密文,得到了明文,即http://test.com/api/orders/这个URL和前面由客户端生成的那个GUID
服务器到一个全局的集合中查找这个GUID,看看是否已经存在,如果存在,则验证不通过,如果不存在,就将其放入这个集合中。这是为了避免重发攻击。这个全局的集合会越来越大,所以还要定期清理。
服务器再比对解密出来的URL和用户真实请求的URL是否一致,如果一致,那么认为这是合法用户,验证通过!
这是大致过程,如果数据库里找不到该用户,或者解密错误,都被认为验证不通过。以下是一些改进:
数据库中的密码最好做一下摘要(MD5之类的),客户端对应地也要做一下。
在生成密文的时候可以考虑加入另外一些不希望被明文传输的敏感内容,甚至可以加入IP地址,并在服务器端验证。
并
非每次都要真正去数据库里拿一次用户信息,也许你有更好的办法,比如一个简单的缓存(不过需要处理缓存更新的问题),或者当你的系统大到一定程度的时候,
你考虑使用统一的服务来获取用户信息,这就不是缓存那么简单了,里面的文章很多,我相信现在大规模的门户网站都有自己的一套复杂的机制,所以表明上看
RESTful Web API很“低效”,但这种RESTFul的思路和模式却在实际中有很大的可塑性和威力。
这种方法应该足够安全了!
密码根本没有在网络上传输,密文采用的是非验证的对称加密,没有密钥就无法逆转,URL验证避免了传统的身份挟持攻击(即拦截一个用户的包并冒充此用户来访问其它的资源,即便无法破解用户密码), 再用GUID来避免了重发攻击,唯一需要担心的是用户泄露了自己的密码。
如何使用 Web API 来对 MVC 应用程序进行身份验证
首先,让我们先更新 API 项目
我们将先对 API 项目进行必要的修改,修改完成之后再切换到 Web 项目对客户端进行更新。
第1步:我们需要一个数据库
在能做任何操作之前我们需要先创建一个数据库。本例中将使用 SQL Server Express。如果你没有安装,可以从这里下载 SQL Server Express。安装完成之后,创建一个名为 CallingWebApiFromMvc 的数据库。这就是第一步要做的。
Api 项目还需要一个数据库连接字符串,否则我们寸步难行。把下面这段代码插入到 Api 项目的Web.config 文件中:
认证(Identity)框架会自动创建我们管理用户所需要的成员关系表,现在不需要担心去提前创建它们。
第2步:添加相关的Nuget包
接下来我们添加用于OWIN和Windows认证的Nuget包。打开包管理控制台,切换Api项目为缺省项目,输入以下命令:
Install-Package Microsoft.AspNet.WebApi.Owin
Install-Package Microsoft.Owin.Host.SystemWeb
Install-Package Microsoft.AspNet.Identity.EntityFramework
Install-Package Microsoft.AspNet.Identity.Owin
使用这些包可以在我们的应用中启动一个OWIN服务器,然后通过EntityFramework把我们的用户保存到SQL Server。
第3步:添加管理用户的Identity类
我们使用基于Windows认证机制之上的Entity框架来管理数据库相关的业务。首先我们需要添加一些用于处理的类。在Api项目里添加一个Identity目录作为我们要添加类的命名空间。然后添加如下的类:
public class ApplicationUser : IdentityUser
{
}
public class ApplicationDbContext : IdentityDbContext
{ public ApplicationDbContext() : base("ApiFromMvcConnection") {}
public static ApplicationDbContext Create()
{ return new ApplicationDbContext();
}
}
注意我们传给基类构造函数的参数ApiFromMvcConnection要和Web.config中的连接字符串中的name相匹配。
public class ApplicationUserManager : UserManager
{ public ApplicationUserManager(IUserStore store) : base(store)
{
} public static ApplicationUserManager Create(IdentityFactoryOptions options, IOwinContext context)
{ var manager = new ApplicationUserManager(new UserStore (context.Get ()));
// Configure validation logic for usernames
manager.UserValidator = new UserValidator (manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = true,
RequireDigit = true,
RequireLowercase = true,
RequireUppercase = true,
}; var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider = new DataProtectorTokenProvider (dataProtectionProvider.Create("ASP.NET Identity"));
} return manager;
}
}
第4步:添加OWIN启动类
为了让我们的应用程序作为OWIN服务器上运行,我们需要在应用程序启动时初始化。我们可以通过一个启动类做到这一点。我们将装点这个类的
OwinStartup属性,因此在应用程序启动时触发。这也意味着,我们可以摆脱的Global.asax和移动它们的
Application_Start代码转换成我们新的启动类。
using Microsoft.Owin;
[assembly: OwinStartup(typeof(Levelnis.Learning.CallingWebApiFromMvc.Api.Startup))]
namespace Levelnis.Learning.CallingWebApiFromMvc.Api
{
using System;
using System.Web.Http;
using Identity;
using Microsoft.Owin.Security.OAuth;
using Owin;
using Providers;
public class Startup
{ public void Configuration(IAppBuilder app)
{
GlobalConfiguration.Configure(WebApiConfig.Register);
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext (ApplicationUserManager.Create); var oAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/api/token"),
Provider = new ApplicationOAuthProvider(),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
AllowInsecureHttp = true
};
// Enable the application to use bearer tokens to authenticate users
app.UseOAuthBearerTokens(oAuthOptions);
}
}
}
在应用程序启动时,我们正在建立自己的服务器。在这里,我们配置令牌端点并设置自己的自定义提供商,我们用我们的用户进行身份验证。在我们的例子中,我们使用了ApplicationOAuthProvider类。让我们来看看现在:
第5步:添加OAuth的提供商
public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
{ public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
context.Validated();
return Task.FromResult (null);
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var userManager = context.OwinContext.GetUserManager ();
var user = await userManager.FindAsync(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "The user name or password is incorrect."); return;
}
var oAuthIdentity = await user.GenerateUserIdentityAsync(userManager, OAuthDefaults.AuthenticationType); var cookiesIdentity = await user.GenerateUserIdentityAsync(userManager, CookieAuthenticationDefaults.AuthenticationType); var properties = CreateProperties(user.UserName); var ticket = new AuthenticationTicket(oAuthIdentity, properties);
context.Validated(ticket);
context.Request.Context.Authentication.SignIn(cookiesIdentity);
}
private static AuthenticationProperties CreateProperties(string userName)
{
var data = new Dictionary
{
{
"userName", userName
}
};
return new AuthenticationProperties(data);
}
}
我们感兴趣的是这里2种方法。第一,ValidateClientAuthentication,只是验证客户端。我们有一个客户端,所以返回成
功。这是一个异步方法签名但没有异步调用发生。正因为如此,我们可以离开了异步修改,但我们必须返回一个任务自己。我们增加了一个名为
GenerateUserIdentityAsync的ApplicationUser,它看起来像这样的方法:
public class ApplicationUser : IdentityUser
{ public async Task GenerateUserIdentityAsync(UserManager manager, string authenticationType)
{
var userIdentity = await manager.CreateIdentityAsync(this, authenticationType);
return userIdentity;
}
}
第6步:注册一个新用户 - API端
所以,我们有到位的所有Identity类管理用户。让我们来看看RegisterController,将新用户保存到我们的数据库。它接受一个RegisterApi模式,这是简单的:
public class RegisterApiModel
{
[Required]
[EmailAddress] public string Email { get; set; }
[Required]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)]
public string Password {
get; set;
}
[Required]
[Display(Name = "Confirm Password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
}
控制器本身,如果注册成功只是返回一个200 OK响应。如果验证失败,则返回401错误请求的响应。
public class RegisterController : ApiController
{ private ApplicationUserManager UserManager
{ get
{ return Request.GetOwinContext().GetUserManager ();
}
} public IHttpActionResult Post(RegisterApiModel model)
{ if (!ModelState.IsValid)
{ return BadRequest(ModelState);
} var user = new ApplicationUser
{
Email = model.Email,
UserName = model.Email,
EmailConfirmed = true
};
var result = UserManager.Create(user, model.Password);
return result.Succeeded ? Ok() : GetErrorResult(result);
}
private IHttpActionResult GetErrorResult(IdentityResult result)
{
if (result == null)
{
return InternalServerError();
}
if (result.Errors != null)
{
foreach (var error in result.Errors)
{
ModelState.AddModelError("", error);
}
}
if (ModelState.IsValid)
{
// No ModelState errors are available to send, so just return an empty BadRequest.
return BadRequest();
}
return BadRequest(ModelState);
}
}
webapi的ActionFilterAttribute可以直接返回数据给客户端吗
------解决思路----------------------
http://blog.csdn.net/starfd/article/details/43524175
//此处暂时以401返回,可调整为其它返回
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
//actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
艹,csdn这是要关门的节奏,回复的功能都出500错误了!
------解决思路----------------------
上面两种返回HttpResponseMessage的方法(构造)都有几种重载,可以传入自定义class,也可以返回StringContent之类的