python周报第十九周

0.本周知识点总结

  • Ajax验证
  • django form 验证
  • CSRF安全
  • Cookie
  • Session
  • model 数据库ORM

1.Ajax验证

应用场景:验证用户输入是否合法

前端Ajax代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        .error-tag {
            color: red;
        }
    </style>
</head>
<body>
    <div>
        <div>
            <input type="text" name="user" />
{#            <span class="error-tag">aaa</span>#}
        </div>
        <div>
            <input type="password" name="pwd" />
        </div>
        <input type="button" value="提交" onclick="DoSubmit();" />
    </div>
    <script src="/static/jquery-1.12.4.js"></script>
    <script>
        function DoSubmit(){
{#            定义一个要传入后端的字典#}
            var input_dict = {};
{#            对所有的input进行循环#}
            $('input').each(function(){
{#                拿到每个input标签用户输入的值#}
                var v = $(this).val();
{#                拿到每个input标签的属性值#}
                var n = $(this).attr('name');
{#                拼接到字典,例如:{"username":"lk"}#}
                input_dict[n] = v;
            });
{#            先把所有的span标签都删除#}
            $("span").remove();
{#            Ajax验证开始#}
            $.ajax({
{#                url:/login/ POST请求 向后端传入字典 类型json#}
                url: '/login/',
                type: 'POST',
                data: input_dict,
                dataType : "json",
{#                拿到后端返回的值,result就是拿到的值,判断是否登陆成功,根据判断进行处理#}
                success: function (result) {
                    if (result.status) {
                        location.href = "https://www.jd.com";
                    } else {
{#                        假如验证失败,result是返回的信息,result.message是总的报错信息,其中有pwd\user的,每一项有相应的message的信息#}
                        $.each(result.message, function(k,v){
{#                            创建span标签#}
                            var tag = document.createElement("span");
                            tag.className = "error-tag";
{#                            span标签内容就是报错信息,v[0]就是报错信息#}
                            tag.innerText = v[0].message;
{#                            利用拼接,根据属性,在input标签下方添加span标签.#}
                            $('input[name="' + k + '"]').after(tag);
                        })
                    }
                },
                error: function () {

                }
            })
        }
    </script>
</body>
</html>

2.Django Form 验证

应用场景:同样是用于用户认证,还<!DOCTYPE html>

<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <style>
        .error-msg{
            color: red;
        }
    </style>
</head>
<body>
    <form action="/login/" method="POST">
        <div>
            <div>
          obj1是字典,是后端传过来的form类生成的,然后obj1.user 是一个标签           {{ obj1.user }}
假如有报错,则生成错误标签 {% if obj1.errors.user %}
<span class="error-msg">{{ obj1.errors.user.0 }}</span> {% endif %} </div> <div> {{ obj1.pwd }} <span class="error-msg">{{ obj1.errors.pwd.0 }}</span> </div> <div> {{ obj1.num }} <span class="error-msg">{{ obj1.errors.num.0 }}</span> </div> <div> {{ obj1.phone }} <span class="error-msg">{{ obj1.errors.phone.0 }}</span> </div> <div> {{ obj1.test }} <span class="error-msg">{{ obj1.errors.test.0 }}</span> </div> <input type="submit" value="提交" /> </div> </form> </body> </html>

后端代码:

 

import re
# 定义手机号格式
def mobile_validate(value):
    mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
    if not mobile_re.match(value):
        raise ValidationError('手机号码格式错误')

# 定义一个form验证类,必须继承forms.Form
# required输入非空限制,error_messages错误提示内容,min_length最小输入长度,max_length最大输入长度,validators可以加函数控制
# forms.类型
# 每个字段名比如user,就是前端input标签的name值.类型默认是text
class LoginForm(forms.Form):
    user = forms.CharField(required=True, error_messages={'required': '用户名不能为空.'}, max_length=6)
    pwd = forms.CharField(required=True,
                          min_length=6,
                          max_length=10,
                          error_messages={'required': '密码不能为空.', 'min_length': "至少6位"})

    num = forms.IntegerField(error_messages={'required': '数字不能空.','invalid': '必须输入数字'})

    phone = forms.CharField(validators=[mobile_validate, ],)

    #test = forms.CharField(widget=forms.Textarea(attrs={'class': 'c1'}))
    test_choices = (
        (0, '上海'),
        (1, '背景'),
    )
    # select标签里要写上里边的option,要以元组的形式带入
    test = forms.IntegerField(widget=forms.Select(choices=test_choices))
def login(request):
    if request.POST:
        objPost = LoginForm(request.POST)
        # is_valid 判断输入是否合法
        ret = objPost.is_valid()
        print("ret:", ret)
        if ret:
            print("clean:", objPost.clean())
            print(objPost.clean())
            print("user", objPost["user"])
        else:
            from django.forms.utils import ErrorDict
            # 报错信息
            print(type(objPost.errors),objPost.errors.as_json())
            # obj1.errors
            pass
        print("objPost:", objPost)
        print("objPost,Type:", type(objPost))
        print("objPost.user:", objPost["user"])
        return render(request, 'login.html',{'obj1': objPost})

python的输出:

ret: False
<class 'django.forms.utils.ErrorDict'> {"user": [{"code": "max_length", "message": "Ensure this value has at most 6 characters (it has 8)."}]}
objPost: <tr><th><label for="id_user">User:</label></th><td><ul class="errorlist"><li>Ensure this value has at most 6 characters (it has 8).</li></ul><input id="id_user" maxlength="6" name="user" type="text" value="11111111" required /></td></tr>
<tr><th><label for="id_pwd">Pwd:</label></th><td><input id="id_pwd" maxlength="10" minlength="6" name="pwd" type="text" value="dddddddddd" required /></td></tr>
<tr><th><label for="id_num">Num:</label></th><td><input id="id_num" name="num" type="number" value="42222222" required /></td></tr>
<tr><th><label for="id_phone">Phone:</label></th><td><input id="id_phone" name="phone" type="text" value="13111112222" required /></td></tr>
<tr><th><label for="id_test">Test:</label></th><td><select id="id_test" name="test" required>
<option value="0" selected="selected">上海</option>
<option value="1">背景</option>
</select></td></tr>
objPost,Type: <class 'day19_app.views.LoginForm'>
objPost.user: <input id="id_user" maxlength="6" name="user" type="text" value="11111111" required />

3.CSRF

当在settings.py中未注释这一行时,就会产生CSRF 安全中间件的审核。

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

如图:

这种情况可以分为三种解决方案:

1.注释掉那行配置,这个不多说

2.form表单验证,在前端代码加入:

<body>
    <form action="/csrf/" method="post">
        {% csrf_token %}   加入这一行!!!!!!
        <input type="text" name="t1"/>
        <input type="submit" value="form提交"/>
    </form>

这时,在浏览器看前端代码就可以看到

这就相当于一层安全认证,当访问时,django会写入浏览器一些数据,如下次带着这个数据访问,就可通过,如没有数据,则会被拦截,这个一般是防止XSS攻击的。

3.Ajax验证。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/csrf/" method="post">
        {% csrf_token %}
        <input type="text" name="t1"/>
        <input type="submit" value="form提交"/>
    </form>
    <input type="button" value="ajax提交" onclick="DoAjax();"/>
    <script src="/static/jquery-1.12.4.js"></script>
    <script src="/static/jquery.cookie.js"></script>
    <script>
        var csrftoken = $.cookie('csrftoken');

        function csrfSafeMethod(method) {
            // these HTTP methods do not require CSRF protection
            return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
        }
        $.ajaxSetup({
            beforeSend: function(xhr, settings) {
                if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                    xhr.setRequestHeader("X-CSRFToken", csrftoken);
                }
            }
        });
{#        主函数#}
        function DoAjax(){
            $.ajax({
                url: "/csrf/",
                type: "POST",
                data : {"k1":"v1"},
                success: function (data) {
                    console.log(data);
                }

            })
        }
    </script>
</body>
</html>

4.cookie

cookie是服务端写入浏览器的,这个要确保浏览器允许写入cookie。

1.设置cookie 

后端代码:

def cookie(request):
    #打印请求cookie
    print(request.COOKIES)
    #返回前端页面
    obj = render(request, 'cookie.html')
    #在浏览器设置cookie:  "k3":"v3",path是只有在访问/cookie时能看到
    obj.set_cookie('k3','v3',path='/cookie/')
    return obj

5.session

cookie是保存在客户端浏览器,session是保存在服务端

USER_LIST = ["lk", "liukai"]

def session_login(request):
    if request.method == "POST":
        # 获取用户名和密码
        u = request.POST.get("user")
        p = request.POST.get("pwd")
        if p == "123" and u in USER_LIST:
            # 在服务端设置session: "user" = "输入的用户名"
            request.session['user'] = u
            return redirect('/session_index/')
    return render(request, "session_login.html")

# 登陆验证,验证服务端是否配置了session
def auth(func):
    def inner(request, *args, **kwargs):
        user = request.session.get('user', None)
        print(user)
        if not user:
            return redirect('/session_login')
        return func(request, *args, **kwargs)
    return inner

# 直接访问index页面,先验证session
@auth
def session_index(request):
    user = request.session.get('user')
    return render(request, "session_index.html", {"user": user})

def session_logout(request):
    del request.session["user"]
    return redirect("/session_login/")

前端代码 session_index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <h1>欢迎:{{ user }}登录</h1>

    <a href="/session_logout/">注销</a>
</body>
</html>
posted @ 2016-09-18 14:53  爱神灬小凯  阅读(261)  评论(0编辑  收藏  举报