java - implementar - spring security oauth2 client
Clientes web y móviles para Spring Security OAuth2 (1)
¿Cómo implemento un proyecto de cliente web para que cuando el usuario inicie sesión en la página protegida o haga clic en el botón de inicio de sesión, se lo redirija a la url OAuth Provider, inicie sesión y se autentique en el cliente web con todas las funciones de usuario y también necesidad de saber qué cliente se utilizó
Desea utilizar OAuth como SSO.
Opción 1, use la nube de primavera https://spring.io/blog/2015/02/03/sso-with-oauth2-angular-js-and-spring-security-part-v
Opción 2, manejar manualmente el proceso de SSO:
en su cliente web, configure la página de inicio de sesión en el servidor OAuth utilizando autorización otorgada.
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable(); // TODO. Enable this!!!
http.authorizeRequests()
.and()
.formLogin()
.loginPage("http://oauth.web.com/oauth/authorize?response_type=code&client_id=webclient&redirect_uri=http://web.com") // manually defining page to login
//.failureUrl("/login?error") // manually defining page for login error
.usernameParameter("email")
.permitAll()
.and()
.logout()
//.logoutUrl("/logout")
.logoutSuccessUrl("/")
.permitAll();
}
una vez finalizado el proceso de autenticación y autorización, se le redirigirá al cliente web con el código de autorización http://web.com/?code=jYWioI
. su cliente web debería intercambiar este código con acceso simbólico en su servidor oauth. En su servidor oauth, cree un punto final para recuperar información del usuario
@RestController
public class UserRestService {
@RequestMapping("/user")
public Principal user(Principal user) {
// you can also return User object with it''s roles
// {"details":...,"principal":{"username":"user",...},"name":"user"}
return user;
}
}
Luego, su cliente web puede acceder a la información de detalles del usuario enviando una solicitud con el acceso simbólico al punto final de descanso anterior y autenticando al usuario en función de la respuesta.
¿Tengo que administrar el token de acceso y siempre incluirlo en la llamada al servidor de recursos o se puede hacer de alguna manera automáticamente?
Cada solicitud debe incluir acceso simbólico. Si desea hacerlo automáticamente, Spring ha proporcionado al cliente Oauth 2 http://projects.spring.io/spring-security-oauth/docs/oauth2.html
Cuál es la mejor manera de implementar seguridad en las aplicaciones móviles que desarrollaré. ¿Debería usar la contraseña grand para esta autenticación, ya que las aplicaciones serán compiladas por mí, donde tendré un nombre de usuario y una contraseña en la pantalla nativa y luego se enviarán al servidor como una autenticación básica a través de SSL?
Dado que está utilizando una pantalla nativa, la concesión de contraseña es suficiente, pero puede almacenar el token de actualización, esto le permitirá solicitar el acceso a token sin repetir el proceso de autenticación.
¿Hay muestras de que puedo echar un vistazo a esa conversación con Spring Security OAuth y devolver los detalles del usuario?
vea el código de muestra anterior o eche un vistazo a este https://spring.io/blog/2015/02/03/sso-with-oauth2-angular-js-and-spring-security-part-v
Estoy tratando de entender OAuth2 y Spring Security OAuth, especialmente el servicio de OAuth Provider. Estoy tratando de implementar lo siguiente:
- Proveedor de OAuth
- Servidor de recursos (servicios web RESTful que deben protegerse con OAuth Provider (1))
- Web Client (una aplicación de cliente web que está protegida con Spring Security pero debe usar OAuth Provider (1) para autenticar al usuario
- Clientes nativos móviles (Android e iOS) que también deberían usar OAuth Provider (1) para la autenticación
Todos estos módulos son independientes entre sí, es decir, están separados en diferentes proyectos y se alojarán en diferentes dominios, como (1) http://oauth.web.com , (2) http://rest.web.com , (3) http://web.com
Mis dos preguntas son:
A. ¿Cómo implemento un proyecto de cliente web para que cuando el usuario inicie sesión en la página protegida o haga clic en el botón de inicio de sesión, se lo redirija a la url OAuth Provider, inicie sesión y se autentique en el cliente web con todos los roles de usuario y también también necesita saber qué cliente fue utilizado. @EnableResourceServer
(de la misma manera en que se implementa el Servidor de Recursos, vea el código a continuación) en este proyecto para obtener los detalles del usuario? ¿Tengo que administrar el token de acceso y siempre incluirlo en la llamada al servidor de recursos o se puede hacer de alguna manera automáticamente?
B. ¿Cuál es la mejor manera de implementar la seguridad en las aplicaciones móviles que desarrollaré? ¿Debo utilizar la contraseña grand para esta autenticación, ya que las aplicaciones serán compiladas por mí, donde tendré un nombre de usuario y una contraseña en la pantalla nativa y luego se enviarán al servidor como una autenticación básica a través de SSL? ¿Hay muestras de que puedo echar un vistazo a esa conversación con Spring Security OAuth y devolver los detalles del usuario?
Aquí está mi implementación de OAuth Project (1) y Resource Project (2):
1. Proveedor de OAuth
Configuraciones del servidor OAuth2 (la mayoría del código fue tomado de AQUÍ )
@Configuration
@EnableAuthorizationServer
public class OAuth2ServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Autowired
DataSource dataSource;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.tokenStore(tokenStore())
.approvalStore(approvalStore())
.authorizationCodeServices(authorizationCodeServices())
;
}
@Bean
public JdbcClientDetailsService clientDetailsService() {
return new JdbcClientDetailsService(dataSource);
}
@Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
@Bean
public ApprovalStore approvalStore() {
return new JdbcApprovalStore(dataSource);
}
@Bean
public AuthorizationCodeServices authorizationCodeServices() {
return new JdbcAuthorizationCodeServices(dataSource);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(clientDetailsService());
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.checkTokenAccess("permitAll()");
}
}
Configuración de seguridad web
@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
@Autowired
private CustomUserDetailsService customUserDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable(); // TODO. Enable this!!!
http.authorizeRequests()
.and()
.formLogin()
// .loginPage("/login") // manually defining page to login
// .failureUrl("/login?error") // manually defining page for login error
.usernameParameter("email")
.permitAll()
.and()
.logout()
// .logoutUrl("/logout")
.logoutSuccessUrl("/")
.permitAll();
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(customUserDetailsService)
.passwordEncoder(new BCryptPasswordEncoder());
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
UserDetailsService (customUserDetailsService)
@Service
public class CustomUserDetailsService implements UserDetailsService{
private final UserService userService;
@Autowired
public CustomUserDetailsService(UserService userService) {
this.userService = userService;
}
public Authority loadUserByUsername(String email) throws UsernameNotFoundException {
User user = userService.getByEmail(email)
.orElseThrow(() -> new UsernameNotFoundException(String.format("User with email=%s was not found", email)));
return new Authority(user);
}
}
2. Servidor de recursos (RESTful WS)
Configuración (la mayoría del código del esqueleto fue tomado de ESTE ejemplo)
@Configuration
@EnableResourceServer
public class OAuth2ResourceConfig extends ResourceServerConfigurerAdapter{
@Autowired
DataSource dataSource;
String RESOURCE_ID = "data_resource";
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
TokenStore tokenStore = new JdbcTokenStore(dataSource);
resources
.resourceId(RESOURCE_ID)
.tokenStore(tokenStore);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
// For some reason we cant just "permitAll" OPTIONS requests which are needed for CORS support. Spring Security
// will respond with an HTTP 401 nonetheless.
// So we just put all other requests types under OAuth control and exclude OPTIONS.
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/**").access("#oauth2.hasScope(''read'')")
.antMatchers(HttpMethod.POST, "/**").access("#oauth2.hasScope(''write'')")
.antMatchers(HttpMethod.PATCH, "/**").access("#oauth2.hasScope(''write'')")
.antMatchers(HttpMethod.PUT, "/**").access("#oauth2.hasScope(''write'')")
.antMatchers(HttpMethod.DELETE, "/**").access("#oauth2.hasScope(''write'')")
.and()
// Add headers required for CORS requests.
.headers().addHeaderWriter((request, response) -> {
response.addHeader("Access-Control-Allow-Origin", "*");
if (request.getMethod().equals("OPTIONS")) {
response.setHeader("Access-Control-Allow-Methods", request.getHeader("Access-Control-Request-Method"));
response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers"));
}
});
}
}
Controlador WS:
@RestController
@RequestMapping(value = "/todos")
public class TodoController {
@Autowired
private TodoRepository todoRepository;
@RequestMapping(method = RequestMethod.GET)
public List<Todo> todos() {
return todoRepository.findAll();
}
// other methods
}