Cześć mam trudnośći w implementacji JWT. Stworzyłem filtr:
public class AuthenticationFilter extends UsernamePasswordAuthenticationFilter
{
private final AuthenticationManager authenticationManager;
public AuthenticationFilter(AuthenticationManager authenticationManager)
{
this.authenticationManager = authenticationManager;
}
@Override
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException {
try {
UserLoginRequestModel creds = new ObjectMapper().readValue(request.getInputStream(),UserLoginRequestModel.class);
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
creds.getEmail(),
creds.getPassword(),
new ArrayList<>());
authenticationManager.authenticate(usernamePasswordAuthenticationToken);
return authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
creds.getEmail(),
creds.getPassword(),
new ArrayList<>()));
}
catch(IOException e)
{
throw new RuntimeException(e);
}
}
@Override
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse res,FilterChain chain, Authentication auth) throws IOException, ServletException
{
String userName = ((User)auth.getPrincipal()).getUsername();
String token = Jwts.builder()
.setSubject(userName)
//.claim("scope","ADMIN")
.setExpiration(new Date(System.currentTimeMillis() + SecurityConstants.EXPIRATION_TIME))
.signWith(SignatureAlgorithm.HS512, SecurityConstants.getTokenSecret())
.compact();
UserService userService = (UserService) SpringApplicationContext.getBean("userServiceImpl");
UserDto userDto = userService.getUser(userName);
res.addHeader(SecurityConstants.HEADER_STRING,SecurityConstants.TOKEN_PREFIX+token);
res.addHeader("UserID",userDto.getUserId());
}
}
public class AuthorizationFilter extends BasicAuthenticationFilter
{
public AuthorizationFilter(AuthenticationManager authManager)
{
super(authManager);
}
@Override
protected void doFilterInternal(HttpServletRequest req,
HttpServletResponse res,FilterChain chain) throws IOException, ServletException
{
String header = req.getHeader(SecurityConstants.HEADER_STRING);
if(header== null || !header.startsWith(SecurityConstants.TOKEN_PREFIX))
{
chain.doFilter(req, res);
return;
}
UsernamePasswordAuthenticationToken authentication = getAuthentication(req);
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(req, res);
}
private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest req)
{
String token = req.getHeader(SecurityConstants.HEADER_STRING);
if(token != null)
{
token = token.replace(SecurityConstants.TOKEN_PREFIX,"");
String user = Jwts.parser()
.setSigningKey(SecurityConstants.getTokenSecret())
.parseClaimsJws(token)
.getBody()
.getSubject();
if(user != null)
{
List<SimpleGrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority("ADMIN"));
return new UsernamePasswordAuthenticationToken(user, null,authorities );
}
}
return null;
}
}
Oraz config:
@EnableWebSecurity
public class WebSecurity extends WebSecurityConfigurerAdapter {
private final UserService userDetailsService;
private final BCryptPasswordEncoder bCryptPasswordEncoder;
public WebSecurity(UserService userDetailsService, BCryptPasswordEncoder bCryptPasswordEncoder) {
super();
this.userDetailsService = userDetailsService;
this.bCryptPasswordEncoder = bCryptPasswordEncoder;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().authorizeRequests().antMatchers(HttpMethod.POST, SecurityConstants.SIGN_UP_URL)
.permitAll()
//.antMatchers(HttpMethod.GET,"/users/showUser/**").hasRole("ADMIN")
.anyRequest()
.authenticated()
.and()
.addFilter(getAuthenticationFilter())
.addFilter(new AuthorizationFilter(authenticationManager()))
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
public AuthenticationFilter getAuthenticationFilter() throws Exception {
final AuthenticationFilter filter = new AuthenticationFilter(authenticationManager());
filter.setFilterProcessesUrl("/users/login");
return filter;
}
}
Rola jest wpisana hardcodem ale tylko na potrzebę testów. Problem polega na tym że nie do końca wiem czy rola jest zapisywana w tokenie. Gdy chcę ograniczać dostęp w oparciu o rolę dostaję brak dostępu. Może ktoś rzuci okiem i coś podpowie.