Я пытаюсь внедрить JWT Token Based Authentication
и Authorization
.Я использую Spring Boot для бэкэнда и Angular 7 в качестве внешнего интерфейса, и моя задача - завершить бэкэнд-работу.Токен на предъявителя успешно генерируется при аутентификации.И я добавил его в заголовок, но когда я пытаюсь получить заголовок, используя request.getHeader(HEADER_STRING)
, это null
.
Так как использовать этот сгенерированный токен для дальнейшей идентификации вошедшего в систему пользователя ИЛИ это внешнее задание дляопределить пользователя после создания токена?
Я использовал пользовательскую страницу входа в Spring Security, и когда я делаю запрос к http://localhost:8080/login
, она содержит две формы входа вместо одной.
Консоль
doFilterInternal header null response.getHeader(HEADER_STRING) null
getAuthenticationToken token: null
doFilterInternal authenticationToken : null null
doFilterInternal header null response.getHeader(HEADER_STRING) null
getAuthenticationToken token: null
doFilterInternal authenticationToken : null null
doFilterInternal header null response.getHeader(HEADER_STRING) null
getAuthenticationToken token: null
doFilterInternal authenticationToken : null null
doFilterInternal header null response.getHeader(HEADER_STRING) null
getAuthenticationToken token: null
doFilterInternal authenticationToken : null null
attemptAuthentication email: rp@gmail.com abcd@A123
2019-03-04 11:33:34.320 INFO 11652 --- [nio-8080-exec-5] o.h.h.i.QueryTranslatorFactoryInitiator : HHH000397: Using ASTQueryTranslatorFactory
Hibernate: select user0_.id as id1_1_, user0_.branch as branch2_1_, user0_.contact as contact3_1_, user0_.createtime as createti4_1_, user0_.designation as designat5_1_, user0_.email as email6_1_, user0_.expreiance as expreian7_1_, user0_.name as name8_1_, user0_.password as password9_1_, user0_.role as role10_1_, user0_.skypeid as skypeid11_1_, user0_.statusenable as statuse12_1_ from user user0_ where user0_.email=?
loadUserByUsername User [user.toString] Role: ROLE_ADMIN
successfulAuthentication username rp@gmail.com
successfulAuthentication bearer Token Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJycEBjeWduZXRpbmZvdGVjaC5jb20iLCJleHAiOjE1NTE3NjU4MTR9.9mLS64W6JBS1RqlEKl1Zmjb8YS03E9k92ITkaFmw35JH4ELIua8Tbkzj0r9crDgdQnxm3YvFKAD9lY3cgoQsNw
doFilterInternal header null response.getHeader(HEADER_STRING) null
getAuthenticationToken token: null
doFilterInternal authenticationToken : null null
doFilterInternal header null response.getHeader(HEADER_STRING) null
getAuthenticationToken token: null
doFilterInternal authenticationToken : null null
doFilterInternal header null response.getHeader(HEADER_STRING) null
getAuthenticationToken token: null
doFilterInternal authenticationToken : null null
JWTAuthenticationFilter.java
public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
private AuthenticationManager authenticationManager;
public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@Autowired
CustomUserDetailService customUserDetailService;
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
try {
System.out.println("attemptAuthentication "+" email: "+request.getParameter("email") + " "+request.getParameter("password"));
//User user = new ObjectMapper().readValue(request.getInputStream(), User.class);
return this.authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken(request.getParameter("email"), request.getParameter("password")));
} catch (Exception 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();
System.out.println("successfulAuthentication "+" username "+username);
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("successfulAuthentication bearer Token "+bearerToken);
response.getWriter().write(bearerToken);
response.addHeader(HEADER_STRING, bearerToken);
response.sendRedirect(SIGN_UP_SUCCESS);
}
}
JWTAhorhorFilter.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);
System.out.println("doFilterInternal header "+header+ " response.getHeader(HEADER_STRING) "+response.getHeader(HEADER_STRING));
if (header == null || !header.startsWith(TOKEN_PREFIX)) {
chain.doFilter(request, response);
}
UsernamePasswordAuthenticationToken authenticationToken = getAuthenticationToken(request);
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
response.addHeader(header, SIGN_UP_URL);
System.out.println("doFilterInternal authenticationToken : "+authenticationToken+ " "+response.getHeader(SIGN_UP_URL));
chain.doFilter(request, response);
}
private UsernamePasswordAuthenticationToken getAuthenticationToken(HttpServletRequest request) {
String token = request.getHeader(HEADER_STRING);
System.out.println("getAuthenticationToken token: "+token);
if (token == null) return null;
String username = Jwts.parser().setSigningKey(SECRET)
.parseClaimsJws(token.replace(TOKEN_PREFIX, ""))
.getBody()
.getSubject();
UserDetails userDetails = customUserDetailService.loadUserByUsername(username);
System.out.println("getAuthenticationToken userDetails "+userDetails.toString()+ " userDetails.getAuthorities() "+userDetails.getAuthorities());
return username != null ?
new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()) : null;
}
}
CustomUserDetailService.java
@Component
public class CustomUserDetailService implements UserDetailsService {
private final UserRepository userRepository;
@Autowired
public CustomUserDetailService(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userRepository.findByEmail(username);
if(user==null)
{
new UsernameNotFoundException("User not found");
return null;
}
else
{
System.out.println("loadUserByUsername "+user.toString()+" Role: "+user.getRole());
List<GrantedAuthority> authorityListAdmin = AuthorityUtils.createAuthorityList("ROLE_USER", "ROLE_ADMIN");
List<GrantedAuthority> authorityListUser = AuthorityUtils.createAuthorityList("ROLE_USER");
return new org.springframework.security.core.userdetails.User
(user.getEmail(), user.getPassword(), user.getRole()=="ADMIN" ? authorityListAdmin : authorityListUser);
}
}
}
SecuriyConfig.java
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter implements WebMvcConfigurer{
@Autowired
private CustomUserDetailService customUserDetailService;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserDetailService).passwordEncoder(new BCryptPasswordEncoder());
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/home").setViewName("home");
registry.addViewController("/").setViewName("login");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
registry.addViewController("/login").setViewName("login");
registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
registry.addViewController("/failure").setViewName("failure");
registry.addViewController("/403").setViewName("403");
}
@Override
protected void configure(HttpSecurity http) throws Exception{
http
.csrf().disable()
.authorizeRequests().antMatchers("/login","/home","/failure").permitAll()
.antMatchers(HttpMethod.POST,"/admin/**").permitAll()//hasRole("ADMIN")
.antMatchers(HttpMethod.PUT,"/admin/**").hasRole("ADMIN")
.antMatchers(HttpMethod.GET,"/admin/**").hasRole("ADMIN")
.antMatchers(HttpMethod.GET,"/user/**").hasAnyRole("ADMIN","USER")
.antMatchers(HttpMethod.POST,"/user/**").hasAnyRole("ADMIN","USER")
.anyRequest().authenticated()
.and()
.addFilter(new JWTAuthenticationFilter(authenticationManager()))
.addFilter(new JWTAuthorizationFilter(authenticationManager(), customUserDetailService))
.exceptionHandling().accessDeniedPage("/403")
.and()
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/login")
.usernameParameter("email")
.passwordParameter("password")
.defaultSuccessUrl("/home",true)
.failureUrl("/failure")
.and()
.logout().logoutUrl("/logout").permitAll();
}
public SecurityConfig(UserDetailsService userDetailsService) {
super();
this.customUserDetailService = customUserDetailService;
}
}
SecurityConstants.java
public class SecurityConstants {
static final String SECRET = "Romil";
static final String TOKEN_PREFIX = "Bearer ";
static final String HEADER_STRING = "Authorization";
static final String SIGN_UP_URL = "/login";
static final String SIGN_UP_SUCCESS = "/home";
static final long EXPIRATION_TIME = 86400000L;
}