Encrypt password in insert statement in postgresql

2019-07-17 06:11发布

New to postgresql. It might be very simple; but am not getting it.

I've this in mysql:

insert into APP_USERS VALUES
(1, 'admin', 'adminemailid','', 'System', 'Administrator', 'SysAdmin', 'CompanyName',
sha('password123'), 'ADMIN', 2,'SCREEN',0);

After referring postgresql documentations on password encryption/hashing and various similar questions on Stackoverflow;

I tried it's equivalent in postgresql as:

insert into APP_USERS VALUES
(1, 'admin', 'adminemailid','', 'System', 'Administrator', 'SysAdmin', 'CompanyName',
crypt('password123',gen_salt('sha1')), 'ADMIN', 2,'SCREEN',0)

But; it throws me an error at function gen_salt():

No function matches the given name and argument types. You might need to add explicit type casts.

(The datatype of column(field) password is character varying.)

I read various manuals on type casting in postgresql and tried casting the function.

But; no use. I came across various similar errors.

Can I know what exactly am missing? or what is the exact way of type casting? Or do I need to add chkpass module (extension) for this?

I already have pgcrypto extension and am using postgresql 9.6.

1条回答
看我几分像从前
2楼-- · 2019-07-17 07:01

It is not the answer actually but a brief explanation how to find the source of the error.

First of all lets find the pgcrypto extension:

select e.extname, n.nspname
from pg_catalog.pg_extension e left join pg_catalog.pg_namespace n on n.oid = e.extnamespace;

It should return something like:

╔════════════════════╤════════════╗
║      extname       │  nspname   ║
╠════════════════════╪════════════╣
║ plpgsql            │ pg_catalog ║
║ adminpack          │ pg_catalog ║
║ plpythonu          │ pg_catalog ║
║ pg_stat_statements │ public     ║
║ plpython3u         │ pg_catalog ║
║ hstore             │ public     ║
║ uuid-ossp          │ public     ║
║ pg_trgm            │ public     ║
║ ltree              │ public     ║
║ tablefunc          │ public     ║
║ unaccent           │ public     ║
║ pgcrypto           │ nd         ║
╚════════════════════╧════════════╝

So the pgcrypto installed in the schema nd in the my database.

Next lets look to the search_path parameter which provide the information where to search DB objects:

show search_path;
╔═════════════════╗
║   search_path   ║
╠═════════════════╣
║ "$user", public ║
╚═════════════════╝

It means that the objects will be searched in the schema with name of the current user and, if nothing found, in the schema public.

Finally lets check the current user:

select current_user;
╔══════════════╗
║ current_user ║
╠══════════════╣
║ postgres     ║
╚══════════════╝

So as you can see the extension installed in the schema nd can not be found using the search_path which actually is postgres, public and we got the error:

select gen_salt('md5');
ERROR:  function gen_salt(unknown) does not exist
LINE 1: select gen_salt('md5');
               ^
HINT:  No function matches the given name and argument types. You might need to add explicit type casts.

There are several ways how to fix it depending of the actual values for your DB mentioned above.

You can move the extension to another schema like:

alter extension pgcrypto set schema public;

You can change the search_path option like:

set search_path to '"$user", public'; -- for the active session only
alter database your_db_name set search_path to '"$user", public'; -- permanently for the database

Finally you could to explicitly specify the schema in the SQL statement:

select schema_where_it_installed.gen_salt('md5');
-- For my example:
select nd.gen_salt('md5');
查看更多
登录 后发表回答