I'm trying to integrate SiteMinder with Spring Security. I have a logout button on home page which is supposed to make http get request to backend. I'm trying to invalidate session and redirect back to home page. It's supposed to automatically navigate to log in page which is set up in apache. unfortunate it's not invalidating session or delete cookies.
This is my
WebSecurityConfigurerAdapter
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(ssoHeaderFilter(), RequestHeaderAuthenticationFilter.class)
.authenticationProvider(ssoAuthProvider())
.logout()
.logoutUrl("/logoutPage")
.logoutSuccessUrl("/login?logout")
.deleteCookies("JSESSIONID", "GPSESSION")
.invalidateHttpSession(true)
.and()
.csrf().disable()
.authorizeRequests()
.antMatchers("/resources/**")
.permitAll()
.antMatchers( "/**")
.hasRole("ADMIN");
}
AuthenticationController
#RequestMapping(value="/logoutPage", method = RequestMethod.GET)
public void logoutPage (HttpServletRequest request, HttpServletResponse response) throws ServletException {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
HttpSession session = request.getSession(false);
request.logout();
}
SSOAuthenticationProvider
public class SSOAuthenticationProvider implements AuthenticationProvider {
private static final Logger LOGGER = LoggerFactory.getLogger(WebSSOAuthenticationProvider.class);
public static final Map<UserAuthority, UserAuthority> roleMap = new HashMap<>();
static {
roleMap.put(UserAuthority.ADMIN, UserAuthority.ADMIN);
}
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
UserDetailsBean user = (UserDetailsBean) authentication.getPrincipal();
LOGGER.info("Inside WebSSOAuthenticationProvider authenticate method");
if(isValidRoles(user.getRoles())){
return new UsernamePasswordAuthenticationToken(user, authentication.getCredentials(),
getAuthoritiesByRoles( user.getRoles()) );
}
throw new BadCredentialsException(user.getFirstName() + " has not valid roles");
}
private boolean isValidRoles(Set<UserAuthority> roles) {
return roles != null && roles.stream().filter(roleMap::containsKey).findAny().isPresent();
}
#Override
public boolean supports(Class<?> authentication) {
return true;
}
private List<GrantedAuthority> getAuthoritiesByRoles(Set<UserAuthority> roles) {
List<GrantedAuthority> authorities = roles.stream().map(v -> v.name()).map(SimpleGrantedAuthority::new).collect(Collectors.toList());
return authorities;
}
SSOAuthenticationFilter
public class SSOAuthenticationFilter extends RequestHeaderAuthenticationFilter {
private static final Logger LOGGER = LoggerFactory.getLogger(SSOAuthenticationFilter.class);
#Value("${project.ui.test.mode:false}")
private boolean guiTestMode;
private String FIRST_NAME = "sso-givenname";
private String LAST_NAME = "sso_surname";
#Override
protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
LOGGER.debug("Working in the test mode for logging");
Enumeration<String> names = request.getHeaderNames();
LOGGER.info("Going to print all http headers");
while (names.hasMoreElements()) {
String name = names.nextElement();
String value = request.getHeader(name);
LOGGER.info("name: " + name + ", value: " + value);
}
UserDetailsBean user = new UserDetailsBean();
if(isTestMode()){
user.setFirstName("Mock");
user.setLastName("User");
user.setRoles(new HashSet<UserAuthority>(Arrays.asList(UserAuthority.ROLE_P_AND_S)));
request.getSession().setAttribute("user" , user);
return user;
}
user.setFirstName(request.getHeader(FIRST_NAME));
user.setLastName(request.getHeader(LAST_NAME));
user.setRoles(new HashSet<UserAuthority>(Arrays.asList(UserAuthority.ROLE_P_AND_S)));
request.getSession().setAttribute("user" , user);
return user;
}
private boolean isTestMode() {
return guiTestMode;
}
}
Related
I am developing a microservices web application.
I have this microservices:
frontEnd service (all html files)
Account service (with Spring Security)
ZuulGateway service
Demo service (a simple rest controller that return a string)
EurekaServer service
My account service works. The login phase works and the JWT creation works. I save it in the header of the response:
response.addHeader("Authorization", "Bearer " + token);
This is the Ajax code in the frontEnd:
/* sign in submit function */
$("#submit").click(function(e) {
e.preventDefault();
$.ajax({ /* Ajax call to AccountMicroservice for login */
url : 'http://localhost:8762/token/generate-token',
type : "POST",
data : {
username : $("#username").val(),
password : $("#password").val()
},
success : function(data) {
console.log(data.token);
window.location.href = 'http://localhost:8762/test';
},
error : function(result) {
alert("Sign in failed!");
console.log(result);
}
});
});
The problems arose with the addition of Spring Cloud Netflix Zuul. The gateway server port is 8762.
Each request to 'http://localhost:8762/token/generate-token' return a 401 error.
These are the Zuul gateway service. I omitted the import.
application.properties:
server.port=8762
spring.application.name=gateway-service
eureka.client.serviceUrl.defaultZone=${EUREKA_SERVER_URL:http://localhost:8761/eureka}
eureka.client.register-with-eureka=true
eureka.client.fetch-registry=true
zuul.routes.test-service.path=/test/**
zuul.routes.test-service.service-id=test-service
zuul.routes.account-service.path=/token/**
zuul.routes.account-service.service-id=account-service
zuul.routes.auth-service.sensitive-headers=Cookie,Set-Cookie
webSecurityConfig:
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private JwtAuthenticationEntryPoint unauthorizedHandler;
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors()
.and()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler)
.and()
.addFilterAfter(new JwtTokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.authorizeRequests()
// allow all who are accessing "auth" service
.antMatchers(HttpMethod.POST, "/token/**", "/signup").permitAll()
// Any other request must be authenticated
.anyRequest().authenticated();
}
//The CORS filter bean - Configures allowed CORS any (source) to any
//(api route and method) endpoint
#Bean
CorsConfigurationSource corsConfigurationSource() {
final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
final CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin(CorsConfiguration.ALL);
//config.addAllowedHeaders(Collections.singletonList(CorsConfiguration.ALL));
config.addAllowedMethod("OPTIONS");
config.addAllowedMethod("HEAD");
config.addAllowedMethod("GET");
config.addAllowedMethod("PUT");
config.addAllowedMethod("POST");
config.addAllowedMethod("DELETE");
config.addAllowedMethod("PATCH");
source.registerCorsConfiguration("/**", config);
return source;
}
}
JwtTokenUtil:
#Component
public class JwtTokenUtil implements Serializable {
public String getUsernameFromToken(String token) {
return getClaimFromToken(token, Claims::getSubject);
}
public Date getExpirationDateFromToken(String token) {
return getClaimFromToken(token, Claims::getExpiration);
}
public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
final Claims claims = getAllClaimsFromToken(token);
return claimsResolver.apply(claims);
}
private Claims getAllClaimsFromToken(String token) {
return Jwts.parser()
.setSigningKey(SIGNING_KEY)
.parseClaimsJws(token)
.getBody();
}
private Boolean isTokenExpired(String token) {
final Date expiration = getExpirationDateFromToken(token);
return expiration.before(new Date());
}
public String generateToken(Authentication authentication) {
final String authorities = authentication.getAuthorities().stream()
.map(GrantedAuthority::getAuthority)
.collect(Collectors.joining(","));
return Jwts.builder()
.setSubject(authentication.getName())
.claim(AUTHORITIES_KEY, authorities)
.signWith(SignatureAlgorithm.HS256, SIGNING_KEY)
.setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + ACCESS_TOKEN_VALIDITY_SECONDS*1000))
.compact();
}
public Boolean validateToken(String token, UserDetails userDetails) {
final String username = getUsernameFromToken(token);
return (
username.equals(userDetails.getUsername())
&& !isTokenExpired(token));
}
UsernamePasswordAuthenticationToken getAuthentication(final String token, final Authentication existingAuth, final UserDetails userDetails) {
final JwtParser jwtParser = Jwts.parser().setSigningKey(SIGNING_KEY);
final Jws<Claims> claimsJws = jwtParser.parseClaimsJws(token);
final Claims claims = claimsJws.getBody();
final Collection<? extends GrantedAuthority> authorities =
Arrays.stream(claims.get(AUTHORITIES_KEY).toString().split(","))
.map(SimpleGrantedAuthority::new)
.collect(Collectors.toList());
return new UsernamePasswordAuthenticationToken(userDetails, "", authorities);
}
}
JwtTokenAuthenticationFilter:
public class JwtTokenAuthenticationFilter extends OncePerRequestFilter {
#Autowired
private UserDetailsService userDetailsService;
#Autowired
private JwtTokenUtil jwtTokenUtil;
#Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
// 1. get the authentication header. Tokens are supposed to be passed in the authentication header
String header = request.getHeader(HEADER_STRING);
String username = null;
String authToken = null;
// 2. validate the header and check the prefix
if (header != null && header.startsWith(TOKEN_PREFIX)) {
// 3. Get the token
authToken = header.replace(TOKEN_PREFIX,"");
try {
username = jwtTokenUtil.getUsernameFromToken(authToken);
System.out.println("\n\n\n\n\n\n\n\n\n\n" + username + "\n\n\n\n\n\n\n\n\n\n");
} catch (IllegalArgumentException e) {
logger.error("c'รจ stato un errore durante il reperimento dello username dal token", e);
}
}
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
// 4. Validate the token
if (jwtTokenUtil.validateToken(authToken, userDetails)) {
//UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, Arrays.asList(new SimpleGrantedAuthority("ROLE_ADMIN")));
UsernamePasswordAuthenticationToken authentication = jwtTokenUtil.getAuthentication(authToken, SecurityContextHolder.getContext().getAuthentication(), userDetails);
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
logger.info("authenticated user " + username + ", setting security context");
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
// go to the next filter in the filter chain
chain.doFilter(request, response);
}
}
JwtAuthenticationEntryPoint:
#Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable {
#Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
String json = String.format("{\"message\": \"%s\"}", authException.getMessage());
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
response.getWriter().write(json);
}
}
constants:
public class Constants {
public static final long ACCESS_TOKEN_VALIDITY_SECONDS = 5*60*60;
public static final String SIGNING_KEY = "devglan123r";
public static final String TOKEN_PREFIX = "Bearer ";
public static final String HEADER_STRING = "Authorization";
public static final String AUTHORITIES_KEY = "scopes";
}
I am trying to do JWT token authentication using spring boot and angular. After login bearer token is created but after that in JWTAuthorizationFilter i am getting null header and because of that it return anonymousUser. Please tell me why i am getting null header.
SecurityConfig.java
#Configuration
#EnableWebSecurity
#EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
#Autowired
private CustomUserDetailService customUserDetailService;
#Bean
public BCryptPasswordEncoder bCryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.
cors().configurationSource(request -> new CorsConfiguration().applyPermitDefaultValues())
.and().csrf().disable()
.authorizeRequests()
.antMatchers("/**").permitAll()
.antMatchers("/manage/**").hasRole("ADMIN")
.antMatchers("/").hasRole("USER")
.and()
.exceptionHandling()
.accessDeniedPage("/access-denied")
.and()
.addFilter(new JWTAuthenticationFilter(authenticationManager()))
.addFilter(new JWTAuthorizationFilter(authenticationManager(), customUserDetailService));
}
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserDetailService).passwordEncoder(new
BCryptPasswordEncoder());
}
}
JWTAuthenticationFilter.java
public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private AuthenticationManager authenticationManager;
public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
#Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
try {
UserDetail user = new ObjectMapper().readValue(request.getInputStream(), UserDetail.class);
return this.authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken(user.getEmail(), user.getPassword()));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
#Override
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain,
Authentication authResult) throws IOException, ServletException {
String username = ((org.springframework.security.core.userdetails.User) authResult.getPrincipal()).getUsername();
String token = Jwts
.builder()
.setSubject(username)
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS512, SECRET)
.compact();
String bearerToken = TOKEN_PREFIX + token;
System.out.println(bearerToken);
response.getWriter().write(bearerToken);
response.addHeader(HEADER_STRING, bearerToken);
}
}
JWTAuthorizationFilter.java
public class JWTAuthorizationFilter extends BasicAuthenticationFilter {
private final CustomUserDetailService customUserDetailService;
public JWTAuthorizationFilter(AuthenticationManager authenticationManager, CustomUserDetailService customUserDetailService) {
super(authenticationManager);
this.customUserDetailService = customUserDetailService;
}
#Override
protected void doFilterInternal(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain) throws IOException, ServletException {
String header = request.getHeader(HEADER_STRING);
if (header == null || !header.startsWith(TOKEN_PREFIX)) {
chain.doFilter(request, response);
return;
}
UsernamePasswordAuthenticationToken authenticationToken = getAuthenticationToken(request);
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
chain.doFilter(request, response);
}
private UsernamePasswordAuthenticationToken getAuthenticationToken(HttpServletRequest request) {
String token = request.getHeader(HEADER_STRING);
if (token == null) return null;
String username = Jwts.parser().setSigningKey(SECRET)
.parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
.getBody()
.getSubject();
UserDetails userDetails = customUserDetailService.loadUserByUsername(username);
return username != null ?
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities())
: null;
}
}
CustomUserDetailService.java
#Component
public class CustomUserDetailService implements UserDetailsService {
private List<GrantedAuthority> role;
#Autowired
private UserDAO userDAO;
/*
* #Autowired public CustomUserDetailService(UserRepository userRepository) {
* this.userRepository = userRepository; }
*/
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = Optional.ofNullable(userDAO.getByEmail(username))
.orElseThrow(() -> new UsernameNotFoundException("User not found"));
List<GrantedAuthority> authorityListAdmin = AuthorityUtils.createAuthorityList("ROLE_ADMIN");
List<GrantedAuthority> authorityListUser = AuthorityUtils.createAuthorityList("ROLE_USER");
if (user.getRole() == "admin") {
role = authorityListAdmin;
} else {
role = authorityListUser;
}
return new org.springframework.security.core.userdetails.User(user.getEmail(), user.getPassword(), role);
}
}
Userinfo.java
private String email;
private String role;
private String password;
Controller
#RequestMapping(value = "/login")
public ModelAndView login(
#RequestParam(name = "error", required = false) String error,
#RequestParam(name = "logout", required = false) String logout,
HttpServletRequest request,
HttpServletResponse response) {
ModelAndView mv = new ModelAndView("login");
HttpSession session= request.getSession(false);
Authentication auth = SecurityContextHolder.getContext()
.getAuthentication();
System.out.println("auth ===" + auth);
System.out.println("logout ===" + logout);
return mv;
}
This is the output on console:
Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJidW50QGdtYWlsLmNvbSIsImV4cCI6MTU5NjExMjcwM30.fBFMDO--8Q_56LT_qbioiT6p3BOxk3L9OrPVTw5EGbf7oJ0ky7W7PuahIYcdjYSL6-OsHY6qq8tPEetlJO7nEg
auth ===org.springframework.security.authentication.AnonymousAuthenticationToken#823df96a: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails#b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
Please tell me what i am missing here.
Your JWTAuthenticationFilter that extends UsernamePasswordAuthenticationFilter overrides successfulAuthentication method which by default calls this line:
SecurityContextHolder.getContext().setAuthentication(authResult);
Your implementation do not have this line so after processing of this filter you still do not have Authentication in Spring context. The next filter that is called is your JWTAuthorizationFilter which tries to read header from same request object as in previous filter. JWTAuthenticationFilter sets this header in response object not in request object. So basically you ends up without authentication because if (header == null || !header.startsWith(TOKEN_PREFIX)) is always true after login flow.
First thing, in the authentication filter token generated and set on the HttpServletResponse header not on the request object's header. Then next the authorization filter checking the request header for token, so there may be the issue of null happened.
Usually authentication and authorization will not be chained like this, but don't know regarding the actual use case you were trying to implement.
I am using Spring Security to build an authentication entry point for my web app. Now mr registration works well aside for the fact that a user is unable to login due to a compilation error resulting from my successHandler() and failureHandler() method.
The error logged is: java.lang.Error: Unresolved compilation problems:
successHandler cannot be resolved to a variable
authenticationFailureHandler cannot be resolved to a variable
I am not sure what I am doing wrong. I am pasting the security configuration code of my spring boot app. Where do I need to add the required variable or parameters (if any) in order to resolve this?
I've tried to create 2 variables with private modifiers that denote to the same parameters of the Handler which still doesn't work
#Configuration
#EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
#Autowired
private BCryptPasswordEncoder bCryptPasswordEncoder;
#Autowired
private DataSource dataSource;
#Value("${spring.queries.users-query}")
private String usersQuery;
#Value("${spring.queries.roles-query}")
private String rolesQuery;
#Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.
jdbcAuthentication()
.usersByUsernameQuery(usersQuery)
.authoritiesByUsernameQuery(rolesQuery)
.dataSource(dataSource)
.passwordEncoder(bCryptPasswordEncoder);
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/login").permitAll()
.antMatchers("/signup_employer").permitAll()
.antMatchers("/registrations").permitAll()
.antMatchers("/admin/**").hasAuthority("ADMIN").anyRequest()
.authenticated().and().csrf().disable()
.formLogin()
.loginPage("/login").failureUrl("/login?error=true")
.defaultSuccessUrl("/admin")
.usernameParameter("email")
.passwordParameter("password")
.successHandler(successHandler)
.failureHandler(authenticationFailureHandler)
.and()
.logout()
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutSuccessUrl("/logout").deleteCookies("JSESSIONID").deleteCookies("my-rememberme")
.logoutSuccessHandler(logoutSuccessHandler())
.and().rememberMe()
.tokenRepository(persistentTokenRepository())
.and()
// .exceptionHandling().accessDeniedHandler(accessDeniedHandler())
//.and()
.headers().cacheControl().disable()
.and().sessionManagement()
.sessionFixation().migrateSession()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.invalidSessionUrl("/invalidSession")
.maximumSessions(1)
.expiredUrl("/invalidSession");
}
#Bean
public PersistentTokenRepository persistentTokenRepository() {
JdbcTokenRepositoryImpl tokenRepositoryImpl = new JdbcTokenRepositoryImpl();
tokenRepositoryImpl.setDataSource(dataSource);
return tokenRepositoryImpl;
}
#Bean
public LogoutSuccessHandler logoutSuccessHandler() {
return new CustomLogoutSuccessHandler();
}
#Bean
public AccessDeniedHandler accessDeniedHandler() {
return new CustomAccessDeniedHandler();
}
#Bean
public AuthenticationEntryPoint unauthorizedEntryPoint() {
return (request, response, authException) -> response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
}
#Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/resources/**", "/static/**", "/css/**", "/email_templates/**", "/error/**", "/font-awesome/**", "/fonts/**", "/res/**", "/vendor/**", "/js/**", "/img/**");
}
#Bean
public SessionRegistry sessionRegistry() {
return new SessionRegistryImpl();
}
}
login success handler:
public class MySimpleUrlAuthenticationSuccessHandler implements
AuthenticationSuccessHandler {
protected final Log logger = LogFactory.getLog(this.getClass());
protected int SessionTimeout = 1 * 60;
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
public MySimpleUrlAuthenticationSuccessHandler() {
super();
}
// API
#Override
public void onAuthenticationSuccess(final HttpServletRequest request, final
HttpServletResponse response, final Authentication authentication) throws
IOException {
handle(request, response, authentication);
clearAuthenticationAttributes(request);
}
// IMPL
protected void handle(final HttpServletRequest request, final
HttpServletResponse response, final Authentication authentication) throws
IOException {
final String targetUrl = determineTargetUrl(authentication);
if (response.isCommitted()) {
logger.debug("Response has already been committed. Unable to
redirect to " + targetUrl);
return;
}
redirectStrategy.sendRedirect(request, response, targetUrl);
}
protected String determineTargetUrl(final Authentication authentication) {
boolean isUser = false;
boolean isAdmin = false;
final Collection<? extends GrantedAuthority> authorities =
authentication.getAuthorities();
for (final GrantedAuthority grantedAuthority : authorities) {
if (grantedAuthority.getAuthority().equals("USER")) {
isUser = true;
break;
} else if (grantedAuthority.getAuthority().equals("ADMIN")) {
isAdmin = true;
break;
}
}
if (isUser) {
return "/homepage.html";
} else if (isAdmin) {
return "/admin";
} else {
throw new IllegalStateException();
}
}
/**
* Removes temporary authentication-related data which may have been stored
in the session
* during the authentication process.
*/
protected final void clearAuthenticationAttributes(final HttpServletRequest
request) {
final HttpSession session = request.getSession(false);
if (session == null) {
return;
}
session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
}
protected RedirectStrategy getRedirectStrategy() {
return redirectStrategy;
}
public void setRedirectStrategy(final RedirectStrategy redirectStrategy) {
this.redirectStrategy = redirectStrategy;
}
}
Those two lines inside the configure(HttpSecurity) method refers to properties/variables which do not seem to exist.
.successHandler(successHandler)
.failureHandler(authenticationFailureHandler)
I see you've created your MySimpleUrlAuthenticationSuccessHandler. Provide an instance of that class to successHandler. And do the same with failureHandler with an instance of your custom/bundled AuthenticationFailureHandler.
I suppose that the warning you mention requires defining the AuthenticationSuccessHandler as Bean.
#Configuration
class MyConfigurationClass {
...
#Bean
AuthenticationSuccessHandler myAuthenticationSuccessHandler() {
return new MyCustomOrBundledAuthenticationSuccessHandler();
}
}
You can then
.successHandler(myAuthenticationSuccessHandler())
In my spring application, the login process is handled by spring security using the UserDetailsService and BCryptPassword classes. When the login is successful, this class redirect the use to the main page:
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
#Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication auth) throws IOException, ServletException {
HttpSession session = request.getSession();
SavedRequest savedReq = (SavedRequest) session.getAttribute(WebAttributes.ACCESS_DENIED_403);
if (savedReq == null) {
response.sendRedirect(request.getContextPath() + "/acesso/home");
}
else {
response.sendRedirect(request.getContextPath() + "/acesso/login?erro=no_permit");
}
}
}
In the jsp page, I can get the username using this expression:
${pageContext.request.remoteUser}
But, in my database, I also have stored the first and last name. I need, in the class above (or in any place possible), pass this data to my view. I try this:
request.getSession().setAttribute("username", "Usuario Teste");
using this in the view: ${username}, but when I run the application, nothing is displayed.
Anyone can point me a way to do that?
my spring security configuration
protected void configure(HttpSecurity http) throws Exception {
http
.csrf()
.disable()
.authorizeRequests()
.antMatchers("/resources/**", "/publico/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/acesso/login").permitAll()
.loginProcessingUrl("/login").permitAll()
.usernameParameter("login")
.passwordParameter("senha")
.successHandler(new CustomAuthenticationSuccessHandler())
.failureHandler(new CustomAuthenticationFailureHandler())
.and()
.exceptionHandling()
.accessDeniedHandler(new CustomAccessDeniedHandler())
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl("/acesso/login").permitAll();
}
UPDATE
Authentication Provider
public class CustomAuthenticationProvider implements AuthenticationProvider {
#Autowired
private UserDetailsService usuario;
#Autowired
private BCryptPasswordEncoder encoder;
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String name = authentication.getName();
String password = authentication.getCredentials().toString();
UserDetails user = usuario.loadUserByUsername(name);
if(encoder.matches(user.getPassword(), password)) {
Authentication auth = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), user.getAuthorities());
return auth;
}
else {
return null;
}
}
#Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
UserDetailsService
#Service
public class AcessoService implements UserDetailsService {
#Autowired
private UsuarioHome accountDao;
#Override
#Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Usuario account = accountDao.findByField("login", username);
if(account==null) {
System.out.println("No such user: " + username);
throw new UsernameNotFoundException("No such user: " + username);
} else if (account.getAutorizacao().isEmpty()) {
System.out.println("User " + username + " has no authorities");
throw new UsernameNotFoundException("User " + username + " has no authorities");
}
List<Permissao> lista = new ArrayList<Permissao>();
int max = account.getAutorizacao().size();
for(int i=0; i<max; i++) {
int max2 = account.getAutorizacao().get(i).getPermissao().size();
for(int j=0; j<max2; j++) {
lista.add(account.getAutorizacao().get(i).getPermissao().get(j));
}
}
boolean accountIsEnabled = true;
boolean accountNonExpired = true;
boolean credentialsNonExpired = true;
boolean accountNonLocked = true;
return new User(account.getLogin(), account.getSenha(), accountIsEnabled, accountNonExpired, credentialsNonExpired, accountNonLocked, getAuthorities(lista));
}
public List<String> getRolesAsList(List<Permissao> list) {
List <String> rolesAsList = new ArrayList<String>();
for(Permissao role : list){
rolesAsList.add(role.getNome());
}
return rolesAsList;
}
public static List<GrantedAuthority> getGrantedAuthorities(List<String> roles) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
for (String role : roles) {
authorities.add(new SimpleGrantedAuthority(role));
}
return authorities;
}
public Collection<? extends GrantedAuthority> getAuthorities(List<Permissao> list) {
List<GrantedAuthority> authList = getGrantedAuthorities(getRolesAsList(list));
return authList;
}
}
Yor are storing your "username" data in session.
You can try to get it in one of this two ways.
request.setAttribute("username", "Usuario Teste"); and then yo can use ${username} EL directly. Or you can use request.getSession().setAttribute("username", "Usuario Teste"); with ${sessionScope.username} EL.
You must to know the differents between session and request scopes.
PD:
Read this.
In another side, to get the username in Spring Sec yo can try to use <sec:authentication property="principal.username" />
And, if you want to use more complex objects than one String as principal, you can extends the UsernamePasswordAuthenticationToken.
Here's my security config :
#Configuration
#EnableWebSecurity
#ComponentScan("lt.nortal.lab.web.security")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
private CustomAuthenticationProvider authenticationProvider;
#Override
public void configure(final WebSecurity web) throws Exception {
// Allow static resources to be served
web.ignoring().antMatchers("/css**", "/js**", "/html**", "/bootstrap");
}
#Override
protected void configure(final HttpSecurity http) throws Exception {
http
.csrf()
.and()
.authorizeRequests()
.antMatchers("/admin**").hasAuthority("admin") // allow public pages
.antMatchers("/login**").permitAll()
.anyRequest().authenticated() // other pages - authenticated only
.and()
.formLogin() // generate login form
.loginPage("/login")
.permitAll() // permit all to access login form (logical)
.and()
.logout().logoutSuccessUrl("/").permitAll(); // Permit all to access logout url
// (logical)
}
#Override
protected void registerAuthentication(final AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider);
}
}
Here's my authetntication provider :
#Component
public class CustomAuthenticationProvider implements AuthenticationProvider {
#Autowired
private LoginService loginService;
#Override
public Authentication authenticate(final Authentication authentication) throws AuthenticationException {
String email = authentication.getName();
String pass = (String) authentication.getCredentials();
User user = loginService.login(email);
if (user == null) {
throw new BadCredentialsException("Invalid email.");
}
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority("user"));
if (user.getRole() == Role.ADMIN) {
authorities.add(new SimpleGrantedAuthority("admin"));
}
return new CustomAuthenticationToken(new AuthenticatedUser(user.getId(), user.getEmail()),
authorities);
}
#Override
public boolean supports(final Class<?> authentication) {
return UsernamePasswordAuthenticationToken.class.equals(authentication);
}
}
login controller:
#Controller
public class LoginLogoutController {
private static final Logger log = LoggerFactory.getLogger(LoginLogoutController.class);
#Autowired
private CurrentUser currentUser;
#Autowired
private LoginService loginService;
/**
* Represents user login form.
*
*/
#RequestMapping(value = "/login", method = RequestMethod.GET)
public String login(final ModelMap model) {
// add login form attribute
model.put("loginForm", new LoginForm());
return "login";
}
/**
* Processes login form.
*
*/
#RequestMapping(value = "/login", method = RequestMethod.POST)
public String processLogin(
final ModelMap model,
final #Valid #ModelAttribute("loginForm") LoginForm loginForm,
final BindingResult bindingResult) {
User user = null;
// lets check for errors
if (!bindingResult.hasErrors()) {
// no errors, lets try to login user.
user = loginService.login(loginForm.getEmail());
if (user == null) {
// something has failed, reject it with a global errror.
bindingResult.reject("login-generic-fail");
}
}
// at this point, we should have a user. If no user - return same login form.
if (user == null) {
return "login";
}
return "redirect:/";
}
}
When I start the server and go to any page I get a blank page, empty html file. I cant seem to figure out whats wrong here. If you need anything else please let me know