这篇文章主要围绕基于restframework进行token验证和restfultoken展开,旨在为您提供一份详细的参考资料。我们将全面介绍基于restframework进行token验证的优缺点,
这篇文章主要围绕基于restframework进行token验证和restful token展开,旨在为您提供一份详细的参考资料。我们将全面介绍基于restframework进行token验证的优缺点,解答restful token的相关问题,同时也会为您带来c# – 使用Entity Framework进行自引用、C# 解耦EntityFramework进行单元测试、Django REST Framework 批量更新 rest_framework_extensions、Django rest framwork 获取 token 值和前端 token 携带方法的实用方法。
本文目录一览:- 基于restframework进行token验证(restful token)
- c# – 使用Entity Framework进行自引用
- C# 解耦EntityFramework进行单元测试
- Django REST Framework 批量更新 rest_framework_extensions
- Django rest framwork 获取 token 值和前端 token 携带方法
基于restframework进行token验证(restful token)
一般情况下,进入到web网站主页都需要进行token或者其它验证,不能在没有登录的情况下可以查看主页的内容,在用户输入用户名密码后,进行校验成功,后台会返回一个token,用于用于下次访问主页或其它页面进行用户认证,一旦认证成功就可以访问了。
1、用户获取token
用户向后台API发送用户名和密码进行校验以及获取token。
methods: {
loginSubmit(formName) {
this.$refs[formName].validate(async (valid) => {
if (valid) {
const res = await this.$http.post(''login'', this.form);
const {data, meta: {message, code}} = res.data;
if (code === 2000) {
//获取token,将token值存储在localStorage
localStorage.setItem(''token'', data.token);
//验证成功后直接跳转到主页
this.$router.push({name: ''home''});
//登陆成功提示
this.$message.success(message)
} else {
this.$message.warning(message)
}
} else {
this.$message.warning("用户名或密码不能为空")
}
});
}
},
2、后台进行验证
class LoginView(APIView):
authentication_classes = [] # 登陆页面免认证,其余的已经全局配置
def post(self, request, *args, **kwargs):
ret = {
"data": {},
"meta": {
"code": 2001,
"message": "用户名或密码错误"
}
}
user_obj = json.loads(str(request._request.body, encoding=''utf8''))
username = user_obj.get(''username'')
password = user_obj.get(''password'')
if username and password:
obj = UserInfo.objects.filter(
username=username, password=password).first()
if obj:
token = get_md5(username)
# 自动去数据库检查,如果没有就创建,否则更新token
UserToken.objects.update_or_create(user=obj, defaults={''token'': token})
ret["data"]["username"] = username
ret["data"]["password"] = password
ret["data"]["token"] = token
ret["meta"]["code"] = 2000
ret["meta"]["message"] = "登陆成功"
else:
pass
else:
pass
return HttpResponse(json.dumps(ret, ensure_ascii=False))
c# – 使用Entity Framework进行自引用
public class Category { public Guid CategoryID { get; set; } public string Name { get; set; } public Guid? ParentID { get; set; } public bool IsTop { get; set; } public string Description { get; set; } public virtual Category parentCategory { get; set; } }
当我在Entity Framework中使用此类时,它只生成父类和子类的一个关系.
如何在语义上区分属性,并在sql Server中生成两个不同的关系,用于获取所有子类别(子关系的子项(递归自上而下)),另一个用于获取所有父类别(父项的父项) (递归自下而上))?像这样的东西:
public virtual ICollection<Category> childCategories { get; set;} public virtual ICollection<Category> parentCategories { get; set;}
我尝试使用模型构建器,但从那里我只能获得一个级别的细节.
解决方法
public IEnumerable<string> GetAllSubordinateEmployeeIdsByUserId(string userId) { // Retrieve only the fields that create the self-referencing relationship from all nodes var employees = (from e in GetAllEmployees() select new { e.Id,e.SupervisorId }); // Dictionary with optimal size for searching Dictionary<string,string> dicEmployees = new Dictionary<string,string>(employees.Count() * 4); // This queue holds any subordinate employees we find so that we may eventually identify their subordinates as well Queue<string> subordinates = new Queue<string>(); // This list holds the child nodes we're searching for List<string> subordinateIds = new List<string>(); // Load the dictionary with all nodes foreach (var e in employees) { dicEmployees.Add(e.Id,e.SupervisorId); } // Get the key (employee's ID) for each value (employee's supervisor's ID) that matches the value we passed in var directReports = (from d in dicEmployees where d.Value == userId select d.Key); // Add the child nodes to the queue foreach (var d in directReports) { subordinates.Enqueue(d); } // While the queue has a node in it... while (subordinates.Count > 0) { // Retrieve the children of the next node in the queue var node = subordinates.Dequeue(); var childNodes = (from e in dicEmployees where e.Value == node select e.Key); if (childNodes.Count() != 0) { // Add the child nodes to the queue foreach (var c in childNodes) { subordinates.Enqueue(c); } } // Add the node from the queue to the list of child nodes subordinateIds.Add(node); } return subordinateIds.AsEnumerable(); }
此外,作为脚注,我在这篇Dictionary optimization文章的帮助下,能够提高字典中的查找效率.
C# 解耦EntityFramework进行单元测试
1. 首先ef的repository需要抽象的行为提到接口中。
例如 :
public interface IXXXContext : IDisposable { IXXXContext NewInstance(); // db sets DbSet<AAABBB> aaa { get; set; } ... // common Database Database { get; } DbContextConfiguration Configuration { get; } int SaveChanges(); Task<int> SaveChangesAsync(); // store pros ... IStorePro1 StorePro1 { get; } ... }
然后就可以使用DataContext和TestDataContext实现这个接口。其中TestDataContext是在UT中使用的,DataContext是自动生成的。
TestDataContext还需要以下几个类进行模拟。
public class TestDbSet<TEntity> : DbSet<TEntity>, IQueryable, IEnumerable<TEntity>, IDbAsyncEnumerable<TEntity> where TEntity : class { ObservableCollection<TEntity> _data; IQueryable _query; public TestDbSet() { _data = new ObservableCollection<TEntity>(); _query = _data.AsQueryable(); } public override TEntity Add(TEntity item) { _data.Add(item); return item; } public override TEntity Remove(TEntity item) { _data.Remove(item); return item; } public override TEntity Attach(TEntity item) { _data.Add(item); return item; } public override TEntity Create() { return Activator.CreateInstance<TEntity>(); } public override TDerivedEntity Create<TDerivedEntity>() { return Activator.CreateInstance<TDerivedEntity>(); } public override ObservableCollection<TEntity> Local { get { return _data; } } Type IQueryable.ElementType { get { return _query.ElementType; } } Expression IQueryable.Expression { get { return _query.Expression; } } IQueryProvider IQueryable.Provider { get { return new TestDbAsyncQueryProvider<TEntity>(_query.Provider); } } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return _data.GetEnumerator(); } IEnumerator<TEntity> IEnumerable<TEntity>.GetEnumerator() { return _data.GetEnumerator(); } IDbAsyncEnumerator<TEntity> IDbAsyncEnumerable<TEntity>.GetAsyncEnumerator() { return new TestDbAsyncEnumerator<TEntity>(_data.GetEnumerator()); } } internal class TestDbAsyncQueryProvider<TEntity> : IDbAsyncQueryProvider { private readonly IQueryProvider _inner; internal TestDbAsyncQueryProvider(IQueryProvider inner) { _inner = inner; } public IQueryable CreateQuery(Expression expression) { return new TestDbAsyncEnumerable<TEntity>(expression); } public IQueryable<TElement> CreateQuery<TElement>(Expression expression) { return new TestDbAsyncEnumerable<TElement>(expression); } public object Execute(Expression expression) { return _inner.Execute(expression); } public TResult Execute<TResult>(Expression expression) { return _inner.Execute<TResult>(expression); } public Task<object> ExecuteAsync(Expression expression, CancellationToken cancellationToken) { return Task.FromResult(Execute(expression)); } public Task<TResult> ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken) { return Task.FromResult(Execute<TResult>(expression)); } } internal class TestDbAsyncEnumerable<T> : EnumerableQuery<T>, IDbAsyncEnumerable<T>, IQueryable<T> { public TestDbAsyncEnumerable(IEnumerable<T> enumerable) : base(enumerable) { } public TestDbAsyncEnumerable(Expression expression) : base(expression) { } public IDbAsyncEnumerator<T> GetAsyncEnumerator() { return new TestDbAsyncEnumerator<T>(this.AsEnumerable().GetEnumerator()); } IDbAsyncEnumerator IDbAsyncEnumerable.GetAsyncEnumerator() { return GetAsyncEnumerator(); } IQueryProvider IQueryable.Provider { get { return new TestDbAsyncQueryProvider<T>(this); } } } internal class TestDbAsyncEnumerator<T> : IDbAsyncEnumerator<T> { private readonly IEnumerator<T> _inner; public TestDbAsyncEnumerator(IEnumerator<T> inner) { _inner = inner; } public void Dispose() { _inner.Dispose(); } public Task<bool> MoveNextAsync(CancellationToken cancellationToken) { return Task.FromResult(_inner.MoveNext()); } public T Current { get { return _inner.Current; } } object IDbAsyncEnumerator.Current { get { return Current; } } }
使用示例:
[TestMethod] public void TestMethod1() { var mockSet = new Mock<DbSet<BLACKLISTED_TICKET>>(); var mockContext = new Mock<TicketDataContextTest>(); mockContext.Setup(m => m.BLACKLISTED_TICKET).Returns(new TestDbSet<BLACKLISTED_TICKET>()); var context = mockContext.Object; context.BLACKLISTED_TICKET.Add(new BLACKLISTED_TICKET() { TicketNumber = "aaa", CreatedDateTime = DateTime.Now, Id = 1, ModifiedDateTime = DateTime.Now, STATUS = "1" }); Assert.IsTrue(context.BLACKLISTED_TICKET.First().Id == 1); }
如果使用了存储过程,需要额外定义存储过程的接口。
例如:
IStorePro { ... } StorePro : IStorePro{ ... } StoreProFake: IStorePro{ }
然后IDataContext负责返回存储过程的实例
IDataContext{ ... IStorePro GetStorePro(); ... }
以上就是C# 解耦EntityFramework进行单元测试的内容。
Django REST Framework 批量更新 rest_framework_extensions
Django REST framework 是一套基于 Django 框架编写 RESTful 风格 API 的组件。
其中 mixins 配合 viewsets 能极其方便简化对数据的增删改查,
但本身并没有对数据的批量更新删除,利用 rest_framework_extensions 扩展包可以轻松帮我们实现这些功能。
安装使用
pip install rest_framework_extensions
views.py
在视图类中继承 ListUpdateModelMixin
1 from rest_framework_extensions.mixins import ListUpdateModelMixin
2 class ShoppingCartViewSet(ListUpdateModelMixin, viewsets.ModelViewSet):
3 pass
settings.py
1 CORS_ALLOW_HEADERS = [''*''] # 允许的请求头
2 CORS_ORIGIN_ALLOW_ALL = True # 允许跨域
3
4 REST_FRAMEWORK_EXTENSIONS = {
5 ''DEFAULT_BULK_OPERATION_HEADER_NAME'': None
6 }
使用浏览器本地测试,在请求头加上:X-BULK-OPERATION: true
使用 patch 方式请求测试成功,状态码 204,不会返回任何东西
使用 PUT 方法批量更新
以上在浏览器使用正常,但发现在微信小程序中并不支持 patch 方法,只能用 put 方法。要么重新再写一个 put 接口,要么更改源码。
ctrl 点击查看 ListUpdateModelMixin 码源,果真只有 put 方法。怎么办?
把 patch 方法复制粘贴一份,改名为 put 即可,同样测试成功。
\Lib\site-packages\rest_framework_extensions\bulk_operations\mixins.py
对于以上修改。对于没有使用虚拟环境的同学,个人建议不要直接修改源码,一定要把整个包拷到项目目录下再修改。
在项目目录下新建 extra_apps 文件夹,用来存放要修改的第三方包。
再在 settings.py 中添加以下。优先从 extra_apps 文件夹导包。
import os
import sys
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0, os.path.join(BASE_DIR, ''extra_apps''))
微信小程序测试正常
Django rest framwork 获取 token 值和前端 token 携带方法
在进行用户校验时,有多种方法:
1、Cookie:默认可以通过脚本文件获取,容易遭受 XSS 攻击(跨站脚本攻击);所有浏览器会让用户自愿选择是否存储至 cookie。
2、Session:session 会在一定时间内保存在服务器上;当访问增多,会比较占用你服务器的性能。
3、Token:在登录时会发放 Token,类似于 “身份证”,在一些发送要权限校验的请求时,在请求头带上 Token 即可通过验证。特点:方便、安全。
在 Django rest framwork 中 获取 token 的方式:
首先需要在 python manage.py 依次 makemigrations 和 migrate ,
此做法是需要将 django 的后台管理操作的对应表迁移到数据库(mysql 的迁移表如下):
其中 authtoken_token 会给 auth_user 中的用户登录时发一个独有的 Token,
前端登录时,需要请求 Token 的 url 为:
需要注意的是一定是 POST 请求,当然了 账号密码一定要对,需要在 auth_user 中相对应数据;
在前端使用 sessionStorage 将 Token 储存下来:
登出时 sessionStorage.removeItem (''token''),清空 token。
使用 ajax 提交时:
Token 放在 ajax 的请求头 headers 中 且需要声明如下图
在后台进行登录判断的具体代码:
request.user.is_authenticated 会校验用户返回是否登录的布尔值。
关于基于restframework进行token验证和restful token的问题我们已经讲解完毕,感谢您的阅读,如果还想了解更多关于c# – 使用Entity Framework进行自引用、C# 解耦EntityFramework进行单元测试、Django REST Framework 批量更新 rest_framework_extensions、Django rest framwork 获取 token 值和前端 token 携带方法等相关内容,可以在本站寻找。
本文标签: