--create a user that you want to use the database as:
create role neil;
--create the user for the web server to connect as:
create role webgui noinherit login password 's3cr3t';
--let webgui set role to neil:
grant neil to webgui; --this looks backwards but is correct.
webgui
現在是neil
組中,所以webgui
可以調用set role neil
。但是,webgui
未繼承neil
的權限。
後來,作爲登錄的WebGUI:
psql -d some_database -U webgui
(enter s3cr3t as password)
set role neil;
webgui
並不需要爲這個superuser
許可。
您想在數據庫會話開始時使用set role
,並在會話結束時將其重置。在Web應用程序中,這對應於從數據庫連接池獲取連接並分別釋放它。以下是使用Tomcat的連接池和Spring Security的示例:
public class SetRoleJdbcInterceptor extends JdbcInterceptor {
@Override
public void reset(ConnectionPool connectionPool, PooledConnection pooledConnection) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if(authentication != null) {
try {
/*
use OWASP's ESAPI to encode the username to avoid SQL Injection. Can't use parameters with SET ROLE. Need to write PG codec.
Or use a whitelist-map approach
*/
String username = ESAPI.encoder().encodeForSQL(MY_CODEC, authentication.getName());
Statement statement = pooledConnection.getConnection().createStatement();
statement.execute("set role \"" + username + "\"");
statement.close();
} catch(SQLException exp){
throw new RuntimeException(exp);
}
}
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if("close".equals(method.getName())){
Statement statement = ((Connection)proxy).createStatement();
statement.execute("reset role");
statement.close();
}
return super.invoke(proxy, method, args);
}
}
我試過兩個命令都無濟於事,如果連接用戶不是超級用戶,我得到權限被拒絕的錯誤。我已經用更多信息更新了這個問題 – 2010-06-09 01:58:00
我相信你的用戶必須是你已經想要設置的角色的成員,並且在他們的用戶上擁有NOINHERITS屬性,以便他們不是默認的。那麼你應該升級和降級。但他們必須成爲這個角色的成員。 – rfusca 2010-06-09 03:26:12