auth认证模块是Django内置集成的一个用户认证模块。
  
  auth认证模块方法
  
  方法 释义
  
  auth.authenticate() 认证校验
  
  auth.login(request,user) 封装认证了的user对象
  
  auth.logout(request) 将session数据都删除,且cookie也失效
  
  auth认证模块示例
  
  from django.shortcuts import render,redirect
  
  from django.contrib import auth
  
  from django.contrib.auth.decorators import login_required
  
  def login(request):
  
  if request.method == "POST":
  
  user = request.POST.get("username")
  
  pwd = request.POST.get("password")
  
  user = auth.authenticate(username=user, password=pwd)
  
  # auth认证校验,如果校验成功返回用户名,否则返回空
  
  if user:
  
  auth.login(request, user)
  
  # 封装认证了的user对象
  
  return redirect("index.html")
  
  return render(request, "login.html")
  
  auth认证模块装饰器使用
  
  装饰器,未登录认证时无法访问 index 默认跳转到指定页面,在setting中 配置LOGIN_URL = "跳转的页面名称" 如:
  
  LOGIN_URL = "login.html"
  
  @login_required
  
  def index(request):
  
  print("登录的用户是:",request.user.username)
  
  return render(request,"index.html")
  
  auth认证模块实例
  
  目录架构
  
  MyDjango
  
  APP
  
  html
  
  css
  
  images
  
  js
  
  static
  
  index.html
  
  login.html
  
  migrations
  
  views
  
  index.py
  
  MyDjango
  
  settings.py
  
  urls.py
  
  wsgi.py
  
  db.sqlite3
  
  manage.py
  
  配置文件
  
  index.html
  
  <!DOCTYPE html>
  
  <html lang="en">
  
  <head>
  
  <meta charset="UTF-8">
  
  <title>wellcome</title>
  
  </head>
  
  <body>
  
  {% csrf_token %}
  
  <h1>wellcome index web !!!</h1>
  
  <a href="login.html">退出</a>
  
  </body>
  
  </html>
  
  login.html
  
  <!DOCTYPE html>
  
  <html lang="en">
  
  <head>
  
  <meta charset="UTF-8">
  
  <title>Title</title>
  
  </head>
  
  <body>
  
  <form method="post" action="login.html">
  
  {% csrf_token %}
  
  用户名:<input type="text" name = "username">
  
  密码: <input type="text" name = "password">
  
  <input type="submit">
  
  </form>
  
  </body>
  
  </html>
  
  index.py
  
  from django.shortcuts import render,redirect,HttpResponse
  
  from django.contrib import auth
  
  from django.contrib.auth.decorators import login_required
  
  def login(request):
  
  auth.logout(request)
  
  if request.method == "POST":
  
  user = request.POST.get("username")
  
  pwd = request.POST.get("password")
  
  print("用户名:",user,"密码:",pwd)
  
  user = auth.authenticate(username=user, password=pwd)
  
  # auth认证校验,如果校验成功返回用户名,否则返回空
  
  if user:
  
  auth.login(request, user)
  
  # 封装认证了的user对象
  
  return redirect("/index.html")
  
  else:
  
  return HttpResponse("登录失败,用户或密码错误!")
  
  return render(request, "login.html")
  
  @login_required
  
  def index(request):
  
  user = request.user.username
  
  print("用户",user,"登录成功!")
  
  return render(request, "index.html",{"user":user})
  
  settings.py
  
  TEMPLATES
  
  'DIRS': [os.path.join(BASE_DIR, 'APP/html/static')]
  
  STATIC_URL = '/static/'
  
  STATICFILES_DIRS = (os.path.join(BASE_DIR,"APP/html/static"),)
  
  STATIC_ROOT = 'APP/html'
  
  LOGIN_URL = "login.html"
  
  urls.py
  
  from django.contrib import admin
  
  from django.urls import path,re_path
  
  from APP.views import index
  
  urlpatterns = [
  
  path('admin/', admin.site.urls),
  
  re_path('^login.html$', index.login),
  
  re_path('^index.html$', index.index),
  
  ]
  
  服务运行
  
  生成数据表
  
  python manage.py makemigrations APP
  
  python manage.py migrate
  
  创建超级用户用于登录测试
  
  python manage.py createsuperuser
  
  服务运行
  
  python manage.py runserver
  
  复制代码
  
  可以看到只增加了一个类,这个类有个特点 1. 它实现了 InvocationHandler 接口 2. 它的 invoke 方法实现了我们的需求。InvocationHandler 是 Java 动态代理定义的一个接口,接口中定义了一个 invoke 方法,我们调用代理对象的任何方法都会变成对 FileWriterInvocationHandler 对象的 invoke 方法的调用, 在 invoke 方法中完成代理的功能并控制对真实对象的调用。如果看到你觉得一头雾水,没关系继续向下看将豁然开朗。
  
  到目前为止我们只看到新增了一个 InvocationHandler 接口的实现类,并没有看到代理对象。之前说过之所以是动态代理是因为在运行时才创建代理类,因此我们需要编写一个驱动程序,动态创建代理对象,完成动态代理的后半部分。
  
  复制代码
  
  package com.cnblogs.duma.dp.proxy.dynamic;
  
  import java.lang.reflect.Proxy;
  
  public class DynamicProxyDriver {
  
  public static void main(String[] args) {
  
  /**
  
  * Proxy.newProxyInstance 包括三个参数
  
  * 第一个参数:定义代理类的 classloader,一般用被代理接口的 classloader
  
  * 第二个参数:需要被代理的接口列表
  
  * 第三个参数:实现了 InvocationHandler 接口的对象
  
  * 返回值:代理对象
  
  */
  
  Writer writer = (Writer) Proxy.newProxyInstance(
  
  Writer.class.getClassLoader(),
  
  new Class[www.baohuayule.com]{Writer.class},
  
  new FileWriterInvocationHandler(new FileWriter())); //这就是动态的原因,运行时才创建代理类
  
  try {
  
  writer.write("file1.txt", "text"); //调用代理对象的write方法
  
  } catch (Exception e) {
  
  e.printStackTrace();
  
  }
  
  writer.write("file2.txt", new byte[]{}); //调用代理对象的write方法
  
  }
  
  }
  
  复制代码
  
  最关的一步是 Proxy.newProxyInstance ,该调用会创建代理对象,该代理对象会将我们需要代理的接口(Writer)和 InvocationHandler 实现类关联起来。这样代理对象就会有 Writer 接口的 2 个方法,针对我们的业务逻辑调用过程为:调用代理对象 writer 的 write 方法写数据 -> 转到 FileWriterInvocationHandler 对象的 invoke 方法,判断磁盘空间是否够用 -> 抛出磁盘空间不足异常或调用 FileWriter 对象的 write 方法写数据。在这里动态代理涉及到了 Writer 接口及其实现类、InvocationHandler 接口及其实现类、代理类。动态代理 UML 类图如下:
  
  可以看到代理类 Proxy 实现了 Writer 接口,因此可以调用 write 方法,同时代理类关联 FileWriterInvocationHandler ,因此对 write 方法的调用会变成对 invoke 方法的调用。
  
  至此,新的需求就完成了,我们结合代理模式谈谈此次需求变更我们用到了哪些好的设计原则。
  
  1. 我们没有在原有 FileWrite 实现类中修改代码, 而是新增了 FileInvocationHandler 实现新需求,这符合设计原则中的开闭原则,即:对扩展开发对修改封闭。改动现有代码容易影响已有的正常代码
  
  2. 我们增加代理之后只是把 Writer writer = new FileWriter() 改为 Writer writer = Proxy.newProxyInstance(...),由于都继承了 Writer 接口,因此不需要修改 writer 的类型, 这符合面向接口的设计原则,让我们尽量少的改动现有代码
  
  动态代理还有一个重要的应用场景,我们可以在 invoke 方法中把待调用的方法名(method)和参数(args)发送到远程服务器,在远程服务器中完成调用并返回一个结果,这其实就是 RPC (remote procedure call),即:远程过程调用。我在阅读 Hadoop 源码过程中发现 Hadoop RPC 将动态代理技术应用在上述场景中。
  
  远程代理
  
  个人觉得上述动态代理第二个应用场景算是远程代理的一个特例,因为远程代理不一定非要动态创建代理对象。接下来我们以 Java RMI 为例, 简单看下远程代理。RMI(remote method invocation)即:远程方法调用,与 RPC 类似,可以让我们像调用 Java 本地方法一样,调用远程的方法。这里就需要一个代理对象,代理对象实现了本地的接口,其中序列化/反序列化以及网络传输都在代理对象中实现, 对我们透明,这也是控制了我们对远程对象的访问。代码如下:
  
  复制代码
  
  import java.rmi.Remote;
  
  import java.rmi.RemoteException;
  
  /**
  
  * 定义一个接口,接口中的方法要在远程调用
  
  */
  
  public interface MyRemote extends Remote {
  
  public String sayHello(www.gouyiflb.cn/ ) throws RemoteException;
  
  }
  
  复制代码
  
  复制代码
  
  import java.net.MalformedURLException;
  
  import java.rmi.Naming;
  
  import java.rmi.RemoteException;
  
  import java.rmi.server.UnicastRemoteObject;
  
  /**
  
  * 定义一个接口的远程实现类
  
  * 为了让远程对象拥有 “远程的” 功能,需要继承 UnicastRemoteObject 类
  
  */
  
  public class MyRemoteImpl extends UnicastRemoteObject implements MyRemote {
  
  protected MyRemoteImpl() throws RemoteException {
  
  }
  
  /**
  
  * 客户端通过 rmi 代理对象调用 sayHello 方法,将会进入到此方法
  
  * @return
  
  * @throws RemoteException
  
  */
  
  @Override
  
  public String sayHello(www.365soke.com) throws RemoteException {
  
  System.out.println("req from client.");
  
  return "Server says, 'Hey'";
  
  }
  
  /**
  
  * 启动远程进程的 main 方法
  
  * @param args
  
  */
  
  public static void main(String[www.lezongyule.com] args) {
  
  try {
  
  MyRemote service = new MyRemoteImpl(www.shengyunyule.cn);
  
  Naming.rebind("RemoteHello", service); //将服务名和对应的服务进行绑定,客户端会根据 RemoteHello 找到远程服务
  
  } catch (RemoteException e) {
  
  e.printStackTrace();
  
  } catch (MalformedURLException e) {
  
  e.printStackTrace();
  
  }
  
  }
  
  }
  
  复制代码
  
  这样我们的远程服务已经写好了,还需要做以下 3 个工作来启动远程服务
  
  1. 生成客户端代理类,需要在 MyRemoteImpl.class 所在的目录中执行 rmic MyRemoteImpl 命令,将会生成 MyRemoteImpl_Stub.class 类。首先,rmic 命令是 jdk 自带命令,所在的目录与 java 和 javac 所在的目录一样;其次,我用的 Idea 创建的普通 Java 工程,我的 MyRemoteImpl.class 文件在“E:\backends\java-backends\java-ex\out\production\java-ex”目录中,以我的工程为例,路径以及命令执行如下:
  
  E:\backends\java-backends\java-ex\out \www.yun-shengyl.com production\java-ex>rmic MyRemoteImpl
  
  2. 启动 rmiregistry,为了远程服务可以注册服务名,在我们的 class 所在的目录(“项目目录\out\production\java-ex”)中执行 rmiregistry 命令
  
  E:\backends\java-backends\java-ex\out\production\java-ex>rmiregistry
  
  3. 运行 MyRemoteImpl 类,启动远程服务进程
  
  继续编写客户端访问代码,客户端代码主要是找到刚刚注册的 RemoteHello 远程服务,并获得代理对象,调用代理对象上的方法。我们可以在同一个工程下,创建 MyRemoteClient 类
  
  复制代码
  
  import java.net.MalformedURLException;
  
  import java.rmi.Naming;
  
  import java.rmi.NotBoundException;
  
  import java.rmi.RemoteException;
  
  public class MyRemoteClient {
  
  public static void main(String[www.suoLaiervip.com] args) {
  
  try {
  
  /**
  
  * 找到远程服务,并返回代理对象
  
  * 该代理对象就是 MyRemoteImpl_Stub 且实现了 MyRemote 接口
  
  */
  
  MyRemote service = (MyRemote) Naming.lookup("rmi://127.0.0.1/RemoteHello");
  
  /**
  
  * 调用代理对象的 sayHello 方法,便会通过代理将调用发送到远程服务进程并返回结果
  
  */
  
  String ret = service.sayHello();
  
  System.out.println(ret);
  
  } catch (RemoteException e) {
  
  e.printStackTrace(www.qwert888.com/);
  
  } catch (NotBoundException e) {
  
  e.printStackTrace();
  
  } catch (MalformedURLException e) {
  
  e.printStackTrace();
  
  }
  
  }
  
  }
  
  复制代码
  
  我们可以直接运行 MyRemoteClient 类,可以看到在刚启动的 MyRemoteImpl 进程中,控制台打印了
  
  req from client.
  
  在 MyRemoteClient 进程的控制台中打印了
  
  Server says, 'Hey'
  
  至此我们的远程代理已经介绍完毕。
  
  虚拟代理
  
  虚拟代理是作为创建开销大的对象的替身。举一个我们常见的例子,在 Web 开发或者移动端开发的时候经常会用到 Image 组件,Image 组件一般要传入一个 URL 参数,从网络上下载图片到本地展示。假设这个组件要等到图片下载完成才有显示,那如果图片较大或者网络较慢,给用户造成不好的体验。解决方法是我们可以先显示一个 loading 状态的默认的本地图片,当远程图片下载完成后重新渲染,替换掉当前的 laoding 状态的图片。用虚拟代理来实现这个技术就可以定义一个 ImageProxy 类型,在该类中初始时候先展示一个默认图片,启动线程创建 Image 对象,Image 对象创建完毕,再重新渲染,替换默认图片。虚拟代理也是控制了对 Image 对象的访问。
  
  总结
  
  本章主要介绍了代理模式,并且我们看到了代理模式常用的几种变形,同时也接触了面向对象的基本的设计原则
  
  动态代理 - 程序运行时动态地创建代理对象,所有的对代理对象方法的调用都会变成对 InvocationHandler 的 invoke 方法的调用
  
  远程代理 - 本地调用代理对象访问远程的方法,无需关心网络通信细节,跟调用本地方法一样
  
  虚拟代理 - 为了创建开销大的对象而存在
  
  可以看到代理模式最核心就是控制,代理对象的目的就是控制对真实对象的访问。

Django进阶-auth集成认证模块的更多相关文章

  1. Django基础八之认证模块---auth

    Django基础八之认证模块---auth 目录 Django基础八之认证模块---auth 1. auth介绍 2. autho常用操作 2.1 创建用户 2.2 验证用户 2.3 验证用户是否登录 ...

  2. Django的auth【认证】模块简介

    首先我们先来复习一下路由别名如何使用,这里仅仅复习一下二级路由的路由别名该如何使用 ·1.在视图函数中使用二级路由别名,需要加上app的名称+“:”+ “路由别名” from django.urls ...

  3. Django之auth登录认证

    前言:我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统.此时我们需要实现包括用户注册.用户登录.用户认证.注销.修改密码等功能,这还真是个麻烦的事情呢. Django作为一个完美主义者的 ...

  4. Django之auth用户认证

    auth模块 from django.contrib import auth django.contrib.auth中提供了许多方法,这里主要介绍其中的三个: authenticate()    提供 ...

  5. Django之auth模块(用户认证)

    auth模块简介 auth模块是对登录认证方法的一种封装,之前我们获取用户输入的用户名及密码后需要自己从user表里查询有没有用户名和密码符合的对象, 而有了auth模块之后就可以很轻松的去验证用户的 ...

  6. (30)auth模块(django自带的用户认证模块)

    Auth模块是Django自带的用户认证模块: 我们在开发一个网站的时候,无可避免的需要设计实现网站的用户系统.此时我们需要实现包括用户注册.用户登录.用户认证.注销.修改密码等功能,这还真是个麻烦的 ...

  7. Django之auth模块用户认证模块

    一.Auth模块 1)auth模块是什么.登录后台使用的账号密码,则就是使用的auth模块创建的表 Auth模块是Django自带的用户认证模块: 我们在开发一个网站的时候,无可避免的需要设计实现网站 ...

  8. 十一、Django认证模块--Auth模块

    一.常规认证方法 我们学生管理之登录实现一文中已经了解了自己写一个登录逻辑的过程: 1.url配置 urlpatterns = [ url(r'^login/$', views.login), url ...

  9. Django的自带认证系统——auth模块

    Django自带的用户认证 auth模块 from django.contrib import auth 备注:使用auth模块时,我们默认使用Django提供的auth_user表,创建数据时,可以 ...

随机推荐

  1. Mysql 中的MVCC原理,undo日志的依赖

    一. MVCC 原理了解   原文点击:MVCC原理浅析 读锁: 也叫共享锁.S锁,若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的 ...

  2. Java 常见编码格式——URL、Base64

    数据编码 我们对数据进行编码是因为在某些情况下,不能直接传输中文字符或者其他字符,比如在设置http协议的头部信息或者cookie时,如果value有中文字符,那么就需要将中文字符使用某种编码方式进行 ...

  3. 在Linux添加PYTHONPATH方法以及修改环境变量方法

    Linux下设置环境变量有三种方法,一种用于当前终端,一种用于当前用户,一种用于所有用户: 一:用于当前终端: 在当前终端中输入: export PATH=$PATH:<你的要加入的路径> ...

  4. 架构 规则引擎 quartz

    通向架构师的道路(第五天)之tomcat集群-群猫乱舞-云栖社区-阿里云https://yq.aliyun.com/articles/259343 商业规则引擎和开源规则引擎的测试对比 - qq_39 ...

  5. PHP中友好的处理方式

    在使用PHP进行开发的时候,由于PHP是弱类型语言的特性,所以,偶尔会遇到一些意想不到的错误.规范我们的编程就变得尤为重要了.下面总结一下,我日常开发中的一些经验,可能有些地方不妥,还请多多斧正,指教 ...

  6. [转帖]NUMA架构的CPU -- 你真的用好了么?

    NUMA架构的CPU -- 你真的用好了么? 本文从NUMA的介绍引出常见的NUMA使用中的陷阱,继而讨论对于NUMA系统的优化方法和一些值得关注的方向. 文章欢迎转载,但转载时请保留本段文字,并置于 ...

  7. scala下划线

    作为函数的参数 一个匿名的函数传递给一个方法或者函数的时候,scala会尽量推断出参数类型.例如一个完整的匿名函数作为参数可以写为 scala> def compute(f: (Double)= ...

  8. git基本操作1

    1.创建版本库 在文件夹下,打开Git Bash Here ,然后执行git init,文件夹中会多出.git文件夹.(.git可能是隐藏的) 2.创建a.txt vim  a.txt ,并添加到版本 ...

  9. 老男孩python学习自修【第二天】字符串用法

    实时处理增量日志最佳实践 主要使用f.seek()和f.tell()实现 字符串处理函数: s.find(substr, start, end) 查找子字符串,找不到则返回-1,找到则返回对应的索引 ...

  10. ajax获得后台传来的一个json值,在js中获得其中的属性值

    首先 ajax的dataType需要设置为json, 默认的text获取属性值在jquery3.2.1中尝试不成功 获得属性值的方式: 类似数组,键值对的方式 下面例子: 设置dataType为jso ...