Yo precisa que soy un estudiante francés en 1er año de Java Desarrollador.
Estoy desarrollando una pequeña aplicación de varios módulos usando: Primavera de arranque, la seguridad Spring, Hibernate, datos de primavera, Spring MVC y thymeleaf.
Me gustaría establecer el usuario en la sesión, o al menos el ID de usuario, al iniciar la sesión. De esta manera no tengo que ponerlo manualmente en la sesión o en el modelo cada vez que lo necesite.
Pero como yo uso la conexión de la seguridad de Primavera y la configuración de autenticación predeterminado, realmente no sé cómo o dónde llamar a un procedimiento de este tipo:
void putUserInHttpSession( HttpSession httpSession ) {
httpSession.setAttribute( "user" , getManagerFactory().getUserManager().findByUserName( SecurityContextHolder.getContext().getAuthentication().getName()) );
}
Puedo hacer que la eahc vez que lo necesito, pero me parece bastante feo no sólo para hacer esto al iniciar la sesión en!
Aquí son lo que yo creo que puede ser que necesite para ayudar a mí (que sería impresionante !!! :)
Mi clase WebSecurityConfig:
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Autowired
private DataSource dataSource;
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// Setting Service to find User in the database.
// And Setting PassswordEncoder
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure( HttpSecurity http ) throws Exception {
http.csrf().disable();
// /userInfo page requires login as ROLE_USER or ROLE_ADMIN.
// If no login, it will redirect to /login page.
http.authorizeRequests().antMatchers(
"/user/**")
.access("hasAnyRole('ROLE_USER', 'ROLE_ADMIN')");
// For ADMIN only.
http.authorizeRequests().antMatchers(
"/admin/**")
.access("hasRole('ROLE_ADMIN')");
// When the user has logged in as XX.
// But access a page that requires role YY,
// AccessDeniedException will be thrown.
http.authorizeRequests().and().exceptionHandling().accessDeniedPage("/public/403");
// Config for Login Form
http.authorizeRequests().and().formLogin()//
// Submit URL of login page.
.loginProcessingUrl("/j_spring_security_check") // Submit URL
.loginPage("/public/login").defaultSuccessUrl("/public/showAtlas")//
.failureUrl("/public/login?error=true")//
.usernameParameter("username")//
.passwordParameter("password")
//Config for Logout Page
.and()
.logout().logoutUrl("/public/logout").logoutSuccessUrl("/public/logoutSuccessful");
http.authorizeRequests().antMatchers(
"/public/**").permitAll();
// The pages does not require login
}
}
Mi clase UserDetailsServiceImpl:
@Service
public class UserDetailsServiceImpl implements UserDetailsService{
@Autowired
private ManagerFactory managerFactory;
// private HttpSession httpSession;
/**
* The authentication method uses the user email, since it is easier to remember for most users
* @param input
* @return a UserDetails object
* @throws UsernameNotFoundException
*/
@Override
public UserDetails loadUserByUsername( String input) throws UsernameNotFoundException {
User user = new User();
if( input.contains( "@" )){
user = this.managerFactory.getUserManager().findByEmail( input );
}
else {
user = this.managerFactory.getUserManager().findByUserName( input );
}
if (user == null) {
throw new UsernameNotFoundException( "User with email " + input + " was not found in the database" );
}
// [ROLE_USER, ROLE_ADMIN,..]
List<String> roleNames = this.managerFactory.getRoleManager().findRoleByUserName(user.getUserName());
List<GrantedAuthority> grantList = new ArrayList<GrantedAuthority>();
if (roleNames != null) {
for (String role : roleNames) {
// ROLE_USER, ROLE_ADMIN,..
GrantedAuthority authority = new SimpleGrantedAuthority(role);
grantList.add(authority);
}
}
return (UserDetails) new org.springframework.security.core.userdetails.User(user.getUserName(),
user.getPassword(), grantList);
}
}
Mi LoginController simple:
@Controller
public class LoginController{
@GetMapping("/public/login")
public String login(Model model ){
return "view/login";
}
@GetMapping("/public/logoutSuccessful")
public String logout(Model model) {
return "view/logoutSuccessful";
}
Entonces, ¿hay una forma sencilla de poner al usuario o ID de usuario en el HttpSession al iniciar la sesión?
¡¡¡Muchas gracias chicos!!!
LA SOLUCIÓN
Crear un CustomAuthenticationSuccessHandler
@Component
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
@Autowired
private ManagerFactory managerFactory;
@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response,
Authentication authentication)
throws IOException, ServletException {
String userName = "";
HttpSession session = request.getSession();
Collection< GrantedAuthority > authorities = null;
if(authentication.getPrincipal() instanceof Principal ) {
userName = ((Principal)authentication.getPrincipal()).getName();
session.setAttribute("role", "none");
}else {
User userSpringSecu = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
session.setAttribute("role", String.valueOf( userSpringSecu.getAuthorities()));
session.setAttribute( "connectedUser" , managerFactory.getUserManager().findByUserName( userSpringSecu.getUsername() ) );
}
response.sendRedirect("/public/showAtlas" );
}
}
Entonces Autowired esta clase y añadirlo en el WebSecurityConfigurerAdapter
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Autowired
private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;
@Autowired
private DataSource dataSource;
@Bean
public BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// Setting Service to find User in the database.
// And Setting PassswordEncoder
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Override
protected void configure( HttpSecurity http ) throws Exception {
http.csrf().disable();
// /userInfo page requires login as ROLE_USER or ROLE_ADMIN.
// If no login, it will redirect to /login page.
http.authorizeRequests().antMatchers(
"/user/**")
.access("hasAnyRole('ROLE_USER', 'ROLE_ADMIN')");
// For ADMIN only.
http.authorizeRequests().antMatchers(
"/admin/**")
.access("hasRole('ROLE_ADMIN')");
// http.exceptionHandling().accessDeniedPage( "/error/403" );
// When the user has logged in as XX.
// But access a page that requires role YY,
// AccessDeniedException will be thrown.
http.authorizeRequests().and().exceptionHandling().accessDeniedPage("/public/403");
// Config for Login Form
http.authorizeRequests().and().formLogin()//
// Submit URL of login page.
.loginProcessingUrl("/j_spring_security_check") // Submit URL
.loginPage("/public/login")
.defaultSuccessUrl("/public/showAtlas")//
.successHandler( customAuthenticationSuccessHandler )
.failureUrl("/public/login?error=true")//
.usernameParameter("username")//
.passwordParameter("password")
//Config for Logout Page
.and()
.logout().logoutUrl("/public/logout").logoutSuccessUrl("/public/logoutSuccessful");
http.authorizeRequests().antMatchers(
"/public/**").permitAll();
// The pages does not require login
}
}
Suponiendo que usted quiere añadir el usuario a la sesión de inicio de sesión seccessful, puede crear el AuthenticationSuccessHandler
, como a continuación y registrarse usandosuccessHandler(new AuthenticationSuccessHandlerImpl())
Actualización: Si creamos el objeto AuthenticationSuccessHandlerImpl
, no va a ser la primavera mananged y por lo tanto autowire
en su Securityconfig
y usarlo como se muestra a continuación.
Aquí la Autowire AuthenticationSuccessHandler
en suWebSecurityConfig
@Autowired
AuthenticationSuccessHandler authenticationSuccessHandler;
y utilizarlo WebSecurityConfig.java
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/resources/**", "/registration").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll().successHandler(authenticationSuccessHandler) // See here
.and()
.logout()
.permitAll();
}
los AuthenticationSuccessHandlerImpl.java
import java.io.IOException;
import java.security.Principal;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;
import com.techdisqus.auth.repository.UserRepository;
@Component
public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHandler{
@Autowired HttpSession session; //autowiring session
@Autowired UserRepository repository; //autowire the user repo
private static final Logger logger = LoggerFactory.getLogger(AuthenticationSuccessHandlerImpl.class);
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication authentication) throws IOException, ServletException {
// TODO Auto-generated method stub
String userName = "";
if(authentication.getPrincipal() instanceof Principal) {
userName = ((Principal)authentication.getPrincipal()).getName();
}else {
userName = ((User)authentication.getPrincipal()).getUsername();
}
logger.info("userName: " + userName);
//HttpSession session = request.getSession();
session.setAttribute("userId", userName);
}
}
Espero que esto ayude.