【问题标题】:How implement the same password code in postgres as in django?如何在 postgres 中实现与 django 相同的密码代码?
【发布时间】:2011-11-17 20:09:15
【问题描述】:

我需要从 django 和我的自定义应用程序访问同一个 BD。

我喜欢在 postgress 9 上实现与 django 中相同的功能。

这是我的尝试:

CREATE EXTENSION pgcrypto
  SCHEMA public;
-- Genera una cadena aleatoria del tamaño especificado
CREATE OR REPLACE FUNCTION random_string(length integer) 
RETURNS TEXT
AS $$
DECLARE
  chars text[] := '{0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z}';
  result text := '';
  i integer := 0;
BEGIN
  IF length < 0 THEN
    raise exception 'Given length cannot be less than 0';
  END IF;

  FOR i IN 1..length LOOP
    result := result || chars[1+random()*(array_length(chars, 1)-1)];
  END LOOP;

  RETURN result;
END;
$$
LANGUAGE plpgsql;

-- Encripta con SHA1 una cadena y retorna el tipo de algoritmo + salt + hash
CREATE OR REPLACE FUNCTION encryp_text(_text text)
RETURNS TEXT
AS $$
DECLARE
    hash text := '';
    salt text := '';
BEGIN
    salt := random_string(12);
    hash := encode( digest(random_string(12) || _text, 'SHA1'), 'hex');

    RETURN 'sha1$' || salt || '$' || hash;
END;
$$
LANGUAGE 'plpgsql';


-- Resetea el pwd del usuario
CREATE OR REPLACE FUNCTION create_user (_username text, _password text, name text, lastname text, email text, isadmin bool, isstaff bool)
RETURNS BOOLEAN
AS $$
BEGIN
    IF isadmin THEN
        isstaff := isadmin;
    END IF;

    INSERT INTO auth_user(
            username, 
            first_name, 
            last_name, 
            email, 
            password, 
            is_staff, 
            is_active, 
            is_superuser)
    VALUES (_username, 
            name,
            lastname,
            email,
            encryp_text(_password),
            isstaff, 
            true,
            isadmin);
END;
$$
LANGUAGE 'plpgsql';
SELECT create_user('sample','123','sample','user','s@s.com',true,true)

但是,在 django 中,当尝试进行身份验证时:

from django.contrib.auth import authenticate
authenticate(username='sample', password='123')

失败了。我需要做什么?

更新:

密码相同:

Django:sha1$46uim9Staj7A$d472909885d27a21bc6e489641e27cc6e4ed25b6 Postgress:sha1$CP5CDALuPntn$d85f6aec18ae781c02cddbaa53e7c92e1b2c7ab1

更新:我忘记了这个问题。如How reimplement BCryptPasswordHasher of django with postgres 9.1 所示已解决并升级到新的 bcrypt 方法。

【问题讨论】:

  • 如果您在 manage.py shell 中创建一个普通的 django 用户并设置它的密码并保存,那么 authenticate() 是否适用于该帐户?你能包括来自select * from auth_user where username in ('sample', 'sample_from_django_shell')的psql的输出吗?
  • 如果在用户表上创建一个插入前触发器不是更容易吗?这样,每次您插入新记录时,它都会加密密码。为此,您可以使用 pgcrypto 中的 crypt() 和 gen_salt()
  • 您能否提供适用于哈希的特定密码?大概是一次性的?
  • 你能把它作为答案吗?我很高兴投票。
  • 对链接的答案进行投票比在此处复制更有意义?

标签: django postgresql authentication pycrypto postgresql-9.1


【解决方案1】:

就目前而言,我们无法真正批评您的代码本身。然而,要重用登录,我的建议是简单地使用 Django 使用的相同例程,并根据需要将它们移植到新的语言或框架。这意味着您在安全方面拥有单一授权点。

请注意,您不能将 SHA 散列密码(任何算法)与 PostgreSQL 本身一起使用,因为 PostgreSQL 将密码存储为用用户名加盐的 md5 散列。除非您有权访问未散列的用户名,否则您无法有效地更改 PostgreSQL 用户帐户。但是,您可能可以编写一个函数,从相同的输入更改 PostgreSQL 和 Django 密码,但您需要小心语句日志记录。另请注意, ALTER USER 在 PostgreSQL 中未参数化,因此您最终不得不使用 pl/pgsql 并执行以下操作:

  EXECUTE $e$ ALTER USER $e$ || quote_ident(in_username) || $e$ WITH PASSWORD $e$ 
      || quote_literal(in_password);

【讨论】:

    【解决方案2】:

    根据要求,我解决了这个问题

    -- Genera una cadena aleatoria del tamaño especificado
    CREATE OR REPLACE FUNCTION random_string(length INTEGER, OUT RETURNS TEXT) 
    AS $$
    DECLARE
      chars TEXT[] := '{0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z}';
      result TEXT := '';
      i INTEGER := 0;
    BEGIN
      IF length < 0 THEN
        raise exception 'Given length cannot be less than 0';
      END IF;
    
      FOR i IN 1..length LOOP
        result := result || chars[1+random()*(array_length(chars, 1)-1)];
      END LOOP;
    
      RETURNS =  result;
    END;
    $$
    LANGUAGE plpgsql;
    
    -- Encripta con SHA1 una cadena y retorna el tipo de algoritmo + salt + hash
    CREATE OR REPLACE FUNCTION encryp_TEXT(_TEXT TEXT, OUT RETURNS TEXT)
    AS $$
    DECLARE
        hash TEXT := '';
        salt TEXT := '';
    BEGIN
        salt := random_string(12);
        hash := encode( libs.digest(salt || _TEXT, 'sha1'), 'hex');
    
        RETURNS =  'sha1$' || salt || '$' || hash;
    END;
    $$
    LANGUAGE 'plpgsql';
    

    但是,新的 django (1.5) 不再适用。正确的版本是How reimplement BCryptPasswordHasher of django with postgres 9.1

    现在:

    -- Encripta con bcrypto una cadena y retorna el tipo de algoritmo + salt + hash, django compatible
    CREATE OR REPLACE FUNCTION encryp_text(_TEXT TEXT, OUT RETURNS TEXT)
    AS $$
    DECLARE
        hash TEXT := '';
        salt TEXT := '';
    BEGIN
        salt := random_string(12);
        hash := libs.crypt(_TEXT,salt);
    
        RETURNS =  'bcrypt$' || hash;
    END;
    $$
    LANGUAGE 'plpgsql';
    

    【讨论】:

      猜你喜欢
      • 2012-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-26
      • 1970-01-01
      • 2023-01-12
      • 2023-03-23
      • 2016-01-06
      相关资源
      最近更新 更多