Created
June 30, 2017 10:33
-
-
Save BohdanLevchenko/d4f0e57a8330d1b737765438278a2d73 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.stackoverflow.so44836531; | |
import java.io.IOException; | |
import javax.servlet.*; | |
import javax.sql.DataSource; | |
import org.springframework.beans.factory.annotation.Autowired; | |
import org.springframework.boot.SpringApplication; | |
import org.springframework.boot.autoconfigure.SpringBootApplication; | |
import org.springframework.boot.autoconfigure.jdbc.*; | |
import org.springframework.context.annotation.Bean; | |
import org.springframework.context.event.EventListener; | |
import org.springframework.jdbc.core.JdbcTemplate; | |
import org.springframework.jdbc.datasource.SimpleDriverDataSource; | |
import org.springframework.jdbc.datasource.UserCredentialsDataSourceAdapter; | |
import org.springframework.security.authentication.event.AuthenticationSuccessEvent; | |
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; | |
import org.springframework.security.config.annotation.web.builders.HttpSecurity; | |
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; | |
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; | |
import org.springframework.security.core.Authentication; | |
import org.springframework.security.core.context.SecurityContextHolder; | |
import org.springframework.security.core.userdetails.User; | |
import org.springframework.stereotype.Component; | |
import org.springframework.web.bind.annotation.GetMapping; | |
import org.springframework.web.bind.annotation.RestController; | |
import org.springframework.web.filter.GenericFilterBean; | |
/** | |
* Application properties: | |
* | |
* spring.datasource.driver-class-name=org.postgresql.Driver | |
* spring.datasource.url=jdbc:postgresql://localhost:5432/postgres | |
* spring.datasource.username=none | |
* spring.datasource.password=none | |
* | |
* Test with: curl -i -u postgres:postgres1 'localhost:8080/home' | |
*/ | |
@SpringBootApplication(exclude = DataSourceAutoConfiguration.class) | |
public class So44836531Application { | |
public static void main(String[] args) { | |
SpringApplication.run(So44836531Application.class, args); | |
} | |
@EnableWebSecurity | |
public static class Security extends WebSecurityConfigurerAdapter { | |
@Override | |
protected void configure(AuthenticationManagerBuilder auth) throws Exception { | |
auth.eraseCredentials(false).inMemoryAuthentication().withUser("postgres").password("postgres1").roles("USER"); | |
} | |
@Override | |
protected void configure(HttpSecurity http) throws Exception { | |
http.httpBasic().and().authorizeRequests().mvcMatchers("/").fullyAuthenticated(); | |
} | |
} | |
@Bean | |
public UserCredentialsDataSourceAdapter dataSource(DataSourceProperties properties) { | |
final UserCredentialsDataSourceAdapter dataSourceAdapter = new UserCredentialsDataSourceAdapter(); | |
dataSourceAdapter.setTargetDataSource(DataSourceBuilder.create() | |
.driverClassName(properties.getDriverClassName()) | |
.url(properties.getUrl()) | |
.username(properties.getUsername()) | |
.password(properties.getPassword()) | |
.type(SimpleDriverDataSource.class) // disable pooling | |
.build()); | |
((SimpleDriverDataSource) dataSourceAdapter.getTargetDataSource()).setDriverClass(org.postgresql.Driver.class); //binder won't set it automatically | |
return dataSourceAdapter; | |
} | |
@Bean | |
JdbcTemplate jdbcTemplate(DataSource dataSource) { | |
return new JdbcTemplate(dataSource); | |
} | |
@Component | |
public static class DataSourceCredentialsFilter extends GenericFilterBean { | |
private final UserCredentialsDataSourceAdapter dataSourceAdapter; | |
@Autowired | |
public DataSourceCredentialsFilter(UserCredentialsDataSourceAdapter dataSourceAdapter) { | |
this.dataSourceAdapter = dataSourceAdapter; | |
} | |
@Override | |
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) | |
throws IOException, ServletException { | |
final Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); | |
final User user = (User) authentication.getPrincipal(); | |
dataSourceAdapter.setCredentialsForCurrentThread(user.getUsername(), user.getPassword()); | |
chain.doFilter(request, response); | |
dataSourceAdapter.removeCredentialsFromCurrentThread(); | |
} | |
} | |
@Component | |
public static class AuthenticationHandler { | |
private final UserCredentialsDataSourceAdapter dataSourceAdapter; | |
@Autowired | |
public AuthenticationHandler(UserCredentialsDataSourceAdapter dataSourceAdapter) { | |
this.dataSourceAdapter = dataSourceAdapter; | |
} | |
@EventListener(classes = AuthenticationSuccessEvent.class) | |
public void authenticationSuccess(AuthenticationSuccessEvent event) { | |
final Authentication authentication = event.getAuthentication(); | |
final User user = (User) authentication.getPrincipal(); | |
dataSourceAdapter.setCredentialsForCurrentThread(user.getUsername(), user.getPassword()); // <- the most important part | |
} | |
} | |
@RestController | |
public static class Api { | |
private final JdbcTemplate jdbcTemplate; | |
@Autowired | |
public Api(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } | |
@GetMapping("/home") | |
public String home() { return jdbcTemplate.queryForObject("select CURRENT_TIMESTAMP", String.class); } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment