WJ's Den


  • 首页

  • 分类

  • 归档

  • 标签

  • 搜索
close

机器学习

发表于 2017-05-17   |   分类于 机器学习   |  

什么是机器学习?

Two definitions of Machine Learning are offered. Arthur Samuel described it as: “the field of study that gives computers the ability to learn without being explicitly programmed.” This is an older, informal definition.”

Tom Mitchell provides a more modern definition: “A computer program is said to learn from experience E with respect to some class of tasks T and performance measure P, if its performance at tasks in T, as measured by P, improves with experience E.“

Example: playing checkers.

E = the experience of playing many games of checkers

T = the task of playing checkers.

P = the probability that the program will win the next game.

In general, any machine learning problem can be assigned to one of two broad classifications:

Supervised learning(监督学习) and Unsupervised learning(无监督学习).

监督学习

在监督学习中,我们获得了一个数据集,并且已经知道我们正确的输出应该是什么样子的,这意味着输入和输出之间有一个关系。

受监督的学习问题分为“回归”和“分类”问题。在回归问题中,我们试图在连续输出中预测结果,这意味着我们正在尝试将输入变量映射到一些连续函数。在分类问题中,我们试图用离散输出来预测结果。换句话说,我们正在尝试将输入变量映射到离散类别。

Example1:

根据房地产市场规模的数据,尝试预测房价。价格作为大小的函数是连续的输出,所以这是一个回归问题。

我们可以将这个例子变成一个分类问题,而不是让我们的产出是关于房子“卖出多于或者低于要价”。在这里,我们将房价分为两类。

Example2:

回归 - 鉴别一个人的图片,我们必须根据给定的图片来预测他们的年龄.

分类 - 鉴别肿瘤患者,我们必须预测肿瘤是恶性还是良性。

无监督学习

无监督学习使我们能够很少或不知道我们的结果应该如何处理问题。我们可以从数据中导出结构,我们不一定知道变量的影响。

我们可以通过基于数据中的变量之间的关系对数据进行聚类来导出该结构。

通过无监督的学习,基于预测结果没有反馈。

Example:

聚类:收集100万个不同的基因,并找到一种自动将这些基因组合成不同变量(如生命周期,位置,作用等)相似或相关的组。

非聚类:“鸡尾酒会算法”,让您在混乱的环境中找到结构。 (即,从鸡尾酒会的声音网格中识别个体声音和音乐)。

代价函数

我们可以使用代价函数来衡量我们的假设函数的准确性。这取决于x的输入和实际输出y的假设的所有结果的平均差异(实际上是平均值的平均值)。



此功能也称为“平方误差函数”或“均方误差”。平均值减半(12)作为计算梯度下降的便利,因为平方函数的导数项将抵消12项。以下图片总结了成本函数的作用:



轮廓图是包含许多轮廓线的图形。两个可变函数的轮廓线在同一行的所有点都具有一个恒定值。这样的图表的例子是下面的图。



采取任何颜色,沿着“圆”走,人们期望得到相同的成本函数值。例如,上面绿线上发现的三个绿点与J(θ0,θ1)具有相同的值,因此它们沿同一行找到。当θ0= 800和θ1= -0.15时,圆圈x显示左侧图形的成本函数值。再取另一个h(x)并绘制其轮廓图,得到以下图形:



当θ0= 360和θ1= 0时,轮廓图中J(θ0,θ1)的值越接近中心,从而降低成本函数误差。现在给出我们的假设函数稍微正斜率导致更好的数据拟合。



上面的图表尽可能地最小化了成本函数,因此θ1和θ0的结果分别为0.12和250左右。将图表上的这些值绘制到右边似乎将我们的观点置于内部最“圆”的中心。

ios10相册等隐私权限设置

发表于 2016-12-20   |   分类于 iOS   |  

崩溃日志示例:

This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app’s Info.plist must contain an NSCameraUsageDescription key with a string value explaining to the user how the app uses this data.

升到iOS10之后,需要在info.plist设置权限的有:

麦克风权限:Privacy - Microphone Usage Description 是否允许此App使用你的麦克风?

相机权限: Privacy - Camera Usage Description 是否允许此App使用你的相机?

相册权限: Privacy - Photo Library Usage Description 是否允许此App访问你的媒体资料库?

通讯录权限: Privacy - Contacts Usage Description 是否允许此App访问你的通讯录?

蓝牙权限:Privacy - Bluetooth Peripheral Usage Description 是否许允此App使用蓝牙?

语音转文字权限:Privacy - Speech Recognition Usage Description 是否允许此App使用语音识别?

日历权限:Privacy - Calendars Usage Description

定位权限:Privacy - Location When In Use Usage Description

定位权限: Privacy - Location Always Usage Description

位置权限:Privacy - Location Usage Description

媒体库权限:Privacy - Media Library Usage Description

健康分享权限:Privacy - Health Share Usage Description

健康更新权限:Privacy - Health Update Usage Description

运动使用权限:Privacy - Motion Usage Description

音乐权限:Privacy - Music Usage Description

提醒使用权限:Privacy - Reminders Usage Description

Siri使用权限:Privacy - Siri Usage Description

电视供应商使用权限:Privacy - TV Provider Usage Description

视频用户账号使用权限:Privacy - Video Subscriber Account Usage Description

利用Python给图片打马赛克

发表于 2016-12-02   |   分类于 Python   |  

思路

利用PIL(Python Image Library)获取图片相应点位的像素值,然后以这些像素为基础重新绘制一张新图。

实现

#!/Library/anaconda/bin/python
# -*- coding: utf-8 -*-

# 实现功能: 给图片打马赛克

from PIL import Image, ImageDraw, ImageFont
import sys

width = 600
height = 600
granularity = 25  # 颗粒度

image = Image.new('RGB', (width, height), (255, 255, 255))
# 创建Font对象:
font = ImageFont.truetype('Arial.ttf', 36)
# 创建Draw对象:
draw = ImageDraw.Draw(image)

# image_name = raw_input('Entering Input ImageName:  ')
image_name = sys.argv[1]
image_file = Image.open(image_name)
image_file = image_file.resize((width, height))  # 调整图片大小


def to_mosaic(file_name):
    for x in range(0, width, granularity):
        for y in range(0, height, granularity):
            r, g, b = file_name.getpixel((x, y))
            draw.rectangle([(x, y), (x + granularity, y + granularity)], fill=(r, g, b), outline=None)  # None即是不加网格


to_mosaic(image_file)
image.save('Mosaic.jpg', 'jpeg')

效果图



Mac OS启动服务浅析

发表于 2016-11-29   |  

起因

之所以分析Mac OS启动项,主要原因是我下载visio for Mac时中了一招,下载到了李鬼,是个pkg文件,安装时提示我可能损害电脑,但是我还是授权了,结果悲剧了。

后果

chrome和firefox首页全部被篡改为名叫snowbitt的搜索引擎,开机后safari和firefox都被默认启动。

解决办法

首页篡改还是比较容易,比如chrome中 setting->重制设置即可,不过它会关闭所有插件,重新打勾开启,然后把启动时网页改过来即可。firefox中直接删相应搜索引擎项无用,只能卸载掉并把/Library/Application Support/Firefox 文件删掉,然后下载新的dmg文件重装即可。

比较麻烦的是开机启动项,系统偏好设置里明明没有启动项,可是开机时还是会启动,于是就深究了下去,发现和Mac OS启动服务有关系。

我们先来看一下Mac OS X的启动原理:

  1. mac固件激活,初始化硬件,加载BootX引导器。

  2. BootX加载内核与内核扩展(kext)。

  3. 内核启动launchd进程。

  4. launchd根据
    /System/Library/LaunchAgents, /System/Library/LaunchDaemons, /Library/LaunchDaemons,
    /Library/LaunchAgents,
    ~/Library/LaunchAgents,里的plist配置,启动服务守护进程。

下面再来理解几个基础概念:

/System/Library和/Library和~/Library目录的区别?

/System/Library目录是存放Apple自己开发的软件。
/Library目录是系统管理员存放的第三方软件。
~/Library/是用户自己存放的第三方软件。

LaunchDaemons和LaunchAgents的区别?

LaunchDaemons是用户未登陆前就启动的服务(守护进程)。
LaunchAgents是用户登陆后启动的服务(守护进程)。

以上所说的plist文件大致格式如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC -//Apple Computer//DTD PLIST 1.0//EN
      http://www.apple.com/DTDs/PropertyList-1.0.dtd >
      <plist version="1.0">
      <dict>
           <key>Label</key>
           <string>com.example.exampled</string>
           <key>ProgramArguments</key>
           <array>
                <string>exampled</string>
           </array>
           <key>KeepAlive</key>
           <true/>
      </dict>
      </plist>

集体参数含义参照Apple官方文档launchd.plist

我进入相应目录,根据最新更新日期,发现新增了几个plist文件,cat下,其中关注到了两个关键参数

KeepAlive: True 进程一直存在

RunAtLoad: True 进程开机就启动

ProgramArguments: /etc/run_app.sh

查看了run_app.sh也是个新增的脚本文件,并存在于/etc目录下面

看了代码大概意思就是10s后开启了某些应用,并篡改了www.google.com

到此破案了,我删除了相关多余plist文件和run_app.sh,重启电脑就正常了,当然把相应参数改为false也是可以的,由于我不需要run_app.sh这个脚本,所以索性彻底删除。

Pool - Python多进程管理

发表于 2016-11-28   |   分类于 Python   |  

在Python中多进程管理使用Pool,可以设定最大进程数n,一次执行n个任务,当有一个进程完成后会有新的进程被添加进Pool。

示例代码:

import multiprocessing
import os, time, random

def Lee():
    print "Run task Lee - %s" % (os.getpid())  # os.getpid()获取当前的进程的ID
    start=time.time()
    time.sleep(random.random()*10)  # random.random()随机生成0-1之间的小数
    end=time.time()
    print 'Task Lee, runs %0.2f seconds.' %(end - start)

def Marlon():
    print "Run task Marlon - %s" % (os.getpid())
    start = time.time()
    time.sleep(random.random()*40)
    end = time.time()
    print 'Task Marlon runs %0.2f seconds.' % (end - start)

def Allen():
    print "Run task Allen - %s" % (os.getpid())
    start = time.time()
    time.sleep(random.random()*30)
    end = time.time()
    print 'Task Allen runs %0.2f seconds.' % (end - start)

def Frank():
    print "Run task Frank - %s" % (os.getpid())
    start = time.time()
    time.sleep(random.random()*20)
    end = time.time()
    print 'Task Frank runs %0.2f seconds.' % (end - start)

if __name__ == '__main__':
    function_list = [Lee, Marlon, Allen, Frank]
    print "parent process %s" % (os.getpid())
    pool = multiprocessing.Pool(2)
    for func in function_list:
        pool.apply_async(func)  # Pool执行函数,apply执行函数,当有一个进程执行完毕后,会添加一个新的进程到pool中
    print 'Waiting for all subprocesses done...'
    pool.close()
    pool.join()  # 调用join之前,一定要先调用close() 函数,否则会出错, close()执行后不会有新的进程加入到pool,join函数等待素有子进程结束
    print 'All subprocesses done.'

Python单例的4种实现方法

发表于 2016-11-28   |   分类于 Python   |  

方法一

实现__new__方法
并在将一个类的实例绑定到类变量_instance上,
如果cls._instance为None说明该类还没有实例化过,实例化该类,并返回
如果cls._instance不为None,直接返回cls._instance

class Singleton(object):
def __new__(cls, *args, **kwargs):
    if not hasattr(cls, '_instance'):
        cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs)
    return cls._instance

class A(Singleton):
def __init__(self, s, v):
    self.s = s
    self.v = v

a = A(1, 5)
b = A(2, 4)

print id(a), a.s
print id(b), b.v

"""
import borg

其他文件调用borg的A类的实例即可调用其属性

eg:

print borg.a.s
print borg.b.v
"""

方法二

共享模式;所谓单例就是所有引用(实例、对象)拥有相同的状态(属性)和行为(方法)
同一个类的所有实例天然拥有相同的行为(方法),
只需要保证同一个类的所有实例具有相同的状态(属性)即可
所有实例共享属性的最简单最直接的方法就是__dict__属性指向(引用)同一个字典(dict)

Tips: 这是一种特殊的单例方式,多个实例对象共享属性a singleton with shared-state among instances

class Borg:
__shared_state = {}

def __init__(self):
    self.__dict__ = self.__shared_state
    self.state = 'Init'

def __str__(self):
    return self.state


class YourBorg(Borg):
    pass

if __name__ == '__main__':
rm1 = Borg()
rm2 = Borg()

rm1.state = 'Idle'
rm2.state = 'Running'

print('rm1: {0}'.format(rm1))
print('rm2: {0}'.format(rm2))

rm2.state = 'Zombie'

print('rm1: {0}'.format(rm1))
print('rm2: {0}'.format(rm2))

print('rm1 id: {0}'.format(id(rm1)))
print('rm2 id: {0}'.format(id(rm2)))

rm3 = YourBorg()

print('rm1: {0}'.format(rm1))
print('rm2: {0}'.format(rm2))
print('rm3: {0}'.format(rm3))

方法三

本质上是方法1的升级(或者说高级版)
使用__metaclass__(元类)的高级python用法

class Basic(type):

def __init__(cls, *args, **kwargs):
    super(Basic, cls).__init__(*args, **kwargs)

def __new__(cls, *args, **kwargs):
    return super(Basic, cls).__new__(cls, *args, **kwargs)

class Foo:
    __metaclass__ = Basic

    Foo.color = 'red'
    Foo.borderWidth = 1

class rect:
    def __init__(self, color, borderWidth):
        self.color = color
        self.borderWidth = borderWidth


if __name__ == '__main__':
    Foo.color = 'blue'
    a = rect(Foo.color, Foo.borderWidth)
    print a.__dict__

"""
from borg import Foo

其他文件调用Foo类的属性即可

eg:

print Foo.color
print Foo.borderWidth
"""

方法四

使用装饰器(decorator),
这是一种更pythonic,更elegant的方法,
单例类本身根本不知道自己是单例的,因为他本身(自己的代码)并不是单例的

def singleton(cls, *args, **kw):
    instances = {}
    def _singleton():
    if cls not in instances:
        instances[cls] = cls(*args, **kw)
        return instances[cls]
    return _singleton

@singleton
class MyClass(object):
    a = 1

def __init__(self, x=0):
    self.x = x

one = MyClass()
two = MyClass()

two.a = 3
print one.a
# 3
print id(one)
# 29660784
print id(two)
# 29660784
print one == two
# True
print one is two
# True
one.x = 1
print one.x
# 1
print two.x
# 1

抽象工厂和builder模式的区别

发表于 2016-11-24   |   分类于 Python   |  

在工厂模式里,我们无需关心产品的各部分是如何被创建的,但在Builder模式里,会把产品的创建过程抽象为多个部分。也就是说工厂模式被关注的是整个产品,而Builder模式被关注的是产品的组成部分的创建过程。

Builder模式的类图:



Factory模式一进一出,Builder模式是分步流水线作业。
当你需要做一系列有序的工作或者按照一定的逻辑来完成创建一个对象时 Builder就派上用场啦。

我们可以看到,Builer模式与工厂模式是极为相似的,但是他们还是有区别的:

一、从结构上来看,Builder模式比工厂模式多了一个“导演类”的角色。
在Builder模式的类图中,假如把这个导演类看做是最终调用的客户端,那么图中剩余的部分就可以看作是一个简单的工厂模式了。

二、两者所创建的产品类型完全不一样。
Factory创建只能是单一的产品(单一在这指它非复合产品),而Builder所创建的产品是复合产品,即产品本身就是由其它部件产品组成的。

举个例子来说,现在要生产一辆车,假设它就只由这三个部分组成:玻璃、轮子、发动机。
对于工厂模式来说,他创建后返回的,只能是玻璃,或者轮子,抑或是发动机。
不管怎么样,他不能向客户返回一辆完整的汽车,要得到一辆完整的汽车,客户必须自己动手去把这些零部件组装成一辆汽车。
从这个意义上来讲,工厂模式中的工厂,只是充当了零件厂的角色。
那Builder又是如何创建产品的呢?在Builder模式中,一般不需要、也不充许向客户返回单个部件,他向客户返回的,仅仅就是一部已经完全组装好的汽车成品。
对于汽车部件的生产细节,客户不需要、也不应该让他们知道。

三、Builder和Factory的差别,还在于他们所生产部件产品所在产品树的问题。
这样说,可能有点拗口。具体来说吧,在工厂模式中,我们知道,一个工厂可以创建多个产品,但一个工厂模式中所创建的某个产品,都会和另一个工厂中所创建的产品在同一棵继承树上。
Builder可以创建出可以创建出风马不相及的产品(虽然我们不这么做),但是Factory模式一般是创建一类产品。


以下贴两端Python的抽象工厂和Builder模式的经典代码:

抽象工厂

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#http://ginstrom.com/scribbles/2007/10/08/design-patterns-python-style/

"""Implementation of the abstract factory pattern"""

import random


class PetShop:

    """A pet shop"""

    def __init__(self, animal_factory=None):
        """pet_factory is our abstract factory.  We can set it at will."""

        self.pet_factory = animal_factory

    def show_pet(self):
        """Creates and shows a pet using the abstract factory"""

        pet = self.pet_factory.get_pet()
        print("We have a lovely {}".format(pet))
        print("It says {}".format(pet.speak()))
        print("We also have {}".format(self.pet_factory.get_food()))


# Stuff that our factory makes

class Dog:

    def speak(self):
        return "woof"

    def __str__(self):
        return "Dog"


class Cat:

    def speak(self):
        return "meow"

    def __str__(self):
        return "Cat"


# Factory classes

class DogFactory:

    def get_pet(self):
        return Dog()

    def get_food(self):
        return "dog food"


class CatFactory:

    def get_pet(self):
        return Cat()

    def get_food(self):
        return "cat food"


# Create the proper family
def get_factory():
    """Let's be dynamic!"""
    return random.choice([DogFactory, CatFactory])()


# Show pets with various factories
if __name__ == "__main__":
    for i in range(3):
        shop = PetShop(get_factory())
        shop.show_pet()
        print("=" * 20)

### OUTPUT ###
# We have a lovely Dog
# It says woof
# We also have dog food
# ====================
# We have a lovely Dog
# It says woof
# We also have dog food
# ====================
# We have a lovely Cat
# It says meow
# We also have cat food
# ====================

Builder模式

#!/usr/bin/python
# -*- coding : utf-8 -*-

"""
@author: Diogenes Augusto Fernandes Herminio <diofeher@gmail.com>https://gist.github.com/420905#file_builder_python.py
"""

# Director
class Director(object):

    def __init__(self):
        self.builder = None

    def construct_building(self):
        self.builder.new_building()
        self.builder.build_floor()
        self.builder.build_size()

    def get_building(self):
        return self.builder.building


# Abstract Builder
class Builder(object):

    def __init__(self):
        self.building = None

    def new_building(self):
        self.building = Building()

    def build_floor(self):
        raise NotImplementedError

    def build_size(self):
        raise NotImplementedError

# Concrete Builder
class BuilderHouse(Builder):

    def build_floor(self):
        self.building.floor = 'One'

    def build_size(self):
        self.building.size = 'Big'


class BuilderFlat(Builder):

    def build_floor(self):
        self.building.floor = 'More than One'

    def build_size(self):
        self.building.size = 'Small'


# Product
class Building(object):

    def __init__(self):
        self.floor = None
        self.size = None

    def __repr__(self):
        return 'Floor: {0.floor} | Size: {0.size}'.format(self)


# Client
if __name__ == "__main__":
    director = Director()
    director.builder = BuilderHouse()
    director.construct_building()
    building = director.get_building()
    print(building)
    director.builder = BuilderFlat()
    director.construct_building()
    building = director.get_building()
    print(building)

### OUTPUT ###
# Floor: One | Size: Big
# Floor: More than One | Size: Small

使用python编写简单的登陆API

发表于 2016-11-14   |   分类于 Python   |  

框架

Flask是一个使用 Python 编写的轻量级 Web 应用框架。其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 。



思路

利用Flask,通过和数据库校验用户名密码来判断是否可以登陆成功。

实现

#!/usr/bin/python
# -*- coding: utf-8 -*-

from flask import Flask, request, render_template, Response
import MySQLdb
import json

app = Flask(__name__)

@app.route('/login', methods=['GET', 'POST'])

def login():
    if request.method == 'POST':
        if valid_login(request.form['username'],
                       request.form['password']):
            return json.dumps({'status': 1, 'data': 'login success'})
        else:
            error = 'Invalid username/password'
            return error
    else:
        return 'Not Support Get'

def valid_login(username,password):

    conn = MySQLdb.connect(
        host='localhost',
        port=3306,
        user='root',
        # passwd='',
        db='Test'
    )

    cur = conn.cursor()
    resp = []

    try:
        sql = "select * from user where name = '%s' and password = '%s'" % (username, password)
        cur.execute(sql)
        resp = cur.fetchall()
        conn.commit()

    except Exception as e:
        print e
        conn.rollback()

    cur.close()
    conn.close()

    return len(resp)

if __name__ == '__main__':
    app.run(host="127.0.0.1", port=8080, debug=True)

部署

pycharm运行xxx.py即可

* Running on http://127.0.0.1:8080/ (Press CTRL+C to quit)
* Restarting with stat
* Debugger is active!
* Debugger pin code: 273-703-379

Mac默认开启apache服务占用了80端口,所以这边暂时使用8080作为测试端口在本地测试。

小结

用Python写Restful风格的webAPI其实蛮方便,也容易部署,小项目容易上手,本文所写API只为好玩,真实项目要考虑更多的东西,比如加密等等。

python图片转字符串画

发表于 2016-11-11   |   分类于 Python   |  

原理

把图片各像素根据灰度值转成不同的自定义字符串然后显示出来。

依赖库

使用第三方库pillow:

sudo -H pip --default-timeout=100 install pillow

实现

#!/usr/bin/python
# -*- coding: utf-8 -*-
from PIL import Image

ascii_char = list("##$&      ")
count = len(ascii_char)

def toText(image_file):
string = ''
for h in range(0, image_file.size[1]):  # h
    for w in range(0, image_file.size[0]):  # w
        r, g, b = image_file.getpixel((w, h))
        gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b)
        unit = 255.0 / len(ascii_char)
        string = string + ascii_char[int(gray / unit)]
    string = string + '\n'
return string


image_file = Image.open("lks.jpg")
image_file = image_file.resize((int(image_file.size[0]*0.2), int(image_file.size[1] * 0.1)))  # 调整图片大小

print u'Info:', image_file.size[0], ' ', image_file.size[1], ' ', count

with open('lks.txt','w') as f:
f.write(toText(image_file))

效果图





SQL注入原理浅析

发表于 2016-11-10   |   分类于 mysql   |  

原理

SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有细致地过滤用户输入的数据,致使非法数据侵入系统。

根据相关技术原理,SQL注入可以分为平台层注入和代码层注入。前者由不安全的数据库配置或数据库平台的漏洞所致;后者主要是由于程序员对输入未进行细致地过滤,从而执行了非法的数据查询。基于此,SQL注入的产生原因通常表现在以下几方面:①不当的类型处理;②不安全的数据库配置;③不合理的查询集处理;④不当的错误处理;⑤转义字符处理不合适;⑥多个提交处理不当。

攻击

API在编写过程中没有过滤用户输入的非法字符串,很容易造成sql注入,以mysql-python为例:

conn = MySQLdb.connect(
  host='localhost',
  port=3306,
  user='root',
  # passwd='',
  db='Test'
)

cur = conn.cursor()

try:
  name = "1 or 1 = 1"
  password = "1 or 1 = 1"
  sql = 'select * from user where name = %s and password = %s'%(name,password)
  cur.execute(sql)
  print cur.fetchall()
  conn.commit()

except Exception as e:
  print e
  conn.rollback()

cur.close()
conn.close()

result:

(('Tom', '0000', '\xe5\xa5\xb3'), ('Alen', '7875', '\xe7\x94\xb7'), ('Jack', '7455', '\xe7\x94\xb7'))

很明显使用简单的"1 or 1 = 1"就欺骗了数据库获取了所以user表内容。

防护

归纳一下,主要有以下几点:

1.永远不要信任用户的输入。对用户的输入进行校验,可以通过正则表达式,或限制长度;对单引号和
双”-“进行转换等。

2.永远不要使用动态拼装sql,可以使用参数化的sql或者直接使用存储过程进行数据查询存取。

3.永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接。

4.不要把机密信息直接存放,加密或者hash掉密码和敏感的信息。

5.应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装

6.sql注入的检测方法一般采取辅助软件或网站平台来检测,软件一般采用sql注入检测工具jsky,网站平台就有亿思网站安全平台检测工具。MDCSOFT SCAN等。采用MDCSOFT-IPS可以有效的防御SQL注入,XSS攻击等。

小结

SQL注入的手法相当灵活,在注入的时候会碰到很多意外的情况。能不能根据具体情况进行分析,构造巧妙的SQL语句,从而成功获取想要的数据,是高手与“菜鸟”的根本区别。😊

123
Paul Ding

Paul Ding

iOS & Python Developer

24 日志
8 分类
19 标签
github zhihu
© 2017 Paul Ding
由 Hexo 强力驱动
主题 - NexT.Mist