I\'m working on a java spring boot project which I\'m trying to get spring security set up for user authentication with JWT, the tutorial I\'m following(and also many tutori
public class MyUserDetails implements UserDetails {
/**
*
*/
private static final long serialVersionUID = 1L;
private User user;
public MyUserDetails(User user) {
this.user = user;
}
@Override
public String getUsername() {
return user.getLogin();
}
@Override
public String getPassword() {
return user.getPassword();
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return user.getGrantedAuthorities();
}
@Override
public boolean isAccountNonExpired() {
return user.getActivated();
}
@Override
public boolean isAccountNonLocked() {
return user.getActivated();
}
@Override
public boolean isCredentialsNonExpired() {
return user.getActivated();
}
@Override
public boolean isEnabled() {
return user.getActivated();
}
}
public class JWTFilter extends GenericFilterBean {
private TokenProvider tokenProvider;
public JWTFilter(TokenProvider tokenProvider) {
this.tokenProvider = tokenProvider;
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String jwt = resolveToken(httpServletRequest);
if (StringUtils.hasText(jwt) && this.tokenProvider.validateToken(jwt)) {
Authentication authentication = this.tokenProvider.getAuthentication(jwt);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
filterChain.doFilter(servletRequest, servletResponse);
}
private String resolveToken(HttpServletRequest request){
String bearerToken1 = RequestUtil.getTokenFromHeader(request);
if (bearerToken1 != null) return bearerToken1;
String jwt = request.getParameter(JWTConfigurer.AUTHORIZATION_TOKEN);
if (StringUtils.hasText(jwt)) {
return jwt;
}
return null;
}
}
@Component("userDetailsService")
public class DomainUserDetailsService implements UserDetailsService {
private final Logger log = LoggerFactory.getLogger(DomainUserDetailsService.class);
private final UserRepository userRepository;
public DomainUserDetailsService(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
@Transactional
public UserDetails loadUserByUsername(final String login) {
log.debug("Authenticating {}", login);
String lowercaseLogin = login.toLowerCase(Locale.ENGLISH);
Optional<User> userByLoginFromDatabase = userRepository.findOneWithRolesByLogin(lowercaseLogin);
return userByLoginFromDatabase.map(user -> new MyUserDetails(user))
.orElseThrow(() -> new UsernameNotFoundException("User " + lowercaseLogin + " was not found in the database"));
}
}
Is there a way that I can only use authentication part in my project or should I use both classes to set up user authentication in spring security?
No, there is no concept of only authentication part, you have wrong perception about spring security, spring security is all about configuration either by using default or by implementing your custom configurations. (AuthenticationFilters
, AuthenticationProviders
, AuthenticationToken
etc)
Spring security puts a WALL(HttpFireWall) before your application in terms of proxy filters or spring managed beans. Request can reach your application if it succeeds in both authentication and authorization part.
it will undergoes
Here in this step Authentication object will be created. From auth object you can get
UserDetails
or AuthenticatedPrincipal
or Principal
)AuthenticationManager
)There will be FilterSecurityInterceptor
which comes almost last in the filter chain which gets Authentication
object from SecurityContext
and gets granted authorities list(roles granted) and it will make a decision whether to allow this request to reach the requested resource or not, decision is made by matching with the allowed AntMatchers configured in HttpSecurityConfiguration
.
Consider the exceptions 401-UnAuthorized and 403-Forbidden. These decisions will be done at the last in the filter chain
401-UnAuthorized: Un authenticated user trying to access secured resource.
403-Forbidden : Authenticated user trying to access restricted resource.
Un authenticated user will be allowed to access non restricted resources and he will not get UnAuthorized error but it is handled by AnonymousAuthenticationFilter
which sets authority ROLE_ANONYMOUS
for unauthenticated user.
Note
Below given filter ordering. where,
Authentication is @order-4
Authorization is @Order-9(Last)
Just to give some idea of filters in spring securityFrom Doc
Spring Security has several areas where patterns you have defined are tested against incoming requests in order to decide how the request should be handled. This occurs when theFilterChainProxy
decides which filter chain a request should be passed through and also when theFilterSecurityInterceptor
decides which security constraints apply to a request. It's important to understand what the mechanism is and what URL value is used when testing against the patterns that you define.
Filter Ordering
The order that filters are defined in the chain is very important. Irrespective of which filters you are actually using, the order should be as follows:
1.ChannelProcessingFilter
, because it might need to redirect to a different protocol
2.SecurityContextPersistenceFilter
, so a SecurityContext can be set up in the SecurityContextHolder at the beginning of a web request, and any changes to the SecurityContext can be copied to theHttpSession
when the web request ends (ready for use with the next web request)
3.ConcurrentSessionFilter
, because it uses theSecurityContextHolder
functionality but needs to update theSessionRegistry
to reflect ongoing requests from the principal
4. Authentication processing mechanisms -UsernamePasswordAuthenticationFilter
, CasAuthenticationFilter, BasicAuthenticationFilter etc - so that the SecurityContextHolder can be modified to contain a valid Authentication request token
5. TheSecurityContextHolderAwareRequestFilter
, if you are using it to install a Spring Security awareHttpServletRequestWrapper
into your servlet container
6.RememberMeAuthenticationFilter
, so that if no earlier authentication processing mechanism updated theSecurityContextHolder
, and the request presents a cookie that enables remember-me services to take place, a suitable remembered Authentication object will be put there
7.AnonymousAuthenticationFilter
, so that if no earlier authentication processing mechanism updated theSecurityContextHolder
, an anonymous Authentication object will be put there
8.ExceptionTranslationFilter
, to catch any Spring Security exceptions so that either an HTTP error response can be returned or an appropriateAuthenticationEntryPoint
can be launched
9.FilterSecurityInterceptor
, to protect web URIs and raise exceptions when access is denied
Finally, if you are new to spring security. My suggestion is to try out maximum examples and spend more time on debug logs and try to understand the flow.