What you desire is called Proxy Authentication. Not sure how well MySQL handles it, but MariaDB does and so does PostgreSQL.
Do you need to use Connection Pooling? How many concurrent users do you expect?
Here's how it would work in PostgreSQL:
create role neil login password 'secret';
create role www noinherit login password 's3cret';
grant neil to www;
When I login, connect to the database as neil/secret
to check that I authenticate.
Then connect to database as www/s3cret
Then SET ROLE neil;
This gives you connection pooling (except for login) and current_user
is neil, for auditing.
In Java, you can use a JdbcInterceptor with Tomcat's connection pool and Spring Security:
public class SetRoleJdbcInterceptor extends JdbcInterceptor {
@Override
public void reset(ConnectionPool connectionPool, PooledConnection pooledConnection) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if(authentication != null) {
try {
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);
}
}