3

Я создаю RESTful API на основе Spring, Jersey, Spring Security и Tomcat. Я нашел этот учебник, который кажется отличным, но он никогда не обсуждает, как фактически аутентифицировать пользователей, которые кажутся важными (Stateless Authentication with Spring Security and JWT)Аутентификация токена безопасности безопасности Как проверить подлинность?

В любом случае, я основывал свою реализацию на этом, и теперь я изо всех сил пытаюсь выяснить, как аутентифицировать и вернуть токен.

Я представил то, что, как я думал, был относительным кодом ниже. Теперь вопрос в том, как я действительно аутентифицирую и получаю токен?

Я дал ему попробовать, но я не получаю токен в заголовках ответов.

@Component 
@Path("/auth") 
@Produces(MediaType.APPLICATION_JSON) 
public class AuthenticationEndPoint { 

    private UserSecurityService userService; 

    @Inject 
    public AuthenticationEndPoint(UserSecurityService userService) { 
     this.userService = userService; 
    } 

    @POST 
    public void doSomething(CredentialsDTO credentials) { 
     SecurityUser user = userService.loadUserByUsername(credentials.getUserName()); 
     UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(user.getUsername(),credentials.getPassword(),user.getAuthorities()); 
     SecurityContextHolder.getContext().setAuthentication(token); 
    } 
} 

Вот моя конфигурация Spring Security

@Configuration 
@EnableGlobalMethodSecurity(prePostEnabled = true) 
@EnableWebSecurity 
@Order(2) 
public class SecurityConfig extends WebSecurityConfigurerAdapter { 

    @Inject 
    private StatelessAuthenticationFilter statelessAuthenticationFilter; 

    @Inject 
    private UserSecurityService userSecurityService; 

    @Inject 
    public SecurityConfig() { 
     super(true); 
    } 

    @Override 
    protected void configure(HttpSecurity http) throws Exception { 
     http 
       .csrf().disable() 
       .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() 
       .exceptionHandling().and() 
       .anonymous().and() 
       .servletApi().and() 
       .headers().cacheControl().and() 
       .authorizeRequests() 

       // allow anonymous resource requests 
       .antMatchers("/").permitAll() 
       .antMatchers("/favicon.ico").permitAll() 
       .antMatchers("/public/**").permitAll() 

       // allow login 
       .antMatchers("/api/auth").permitAll() 

       // all other requests require authentication 
       .anyRequest().authenticated().and() 

       // token based authentication 
       .addFilterBefore(statelessAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); 
    } 

    @Override 
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
     auth.userDetailsService(userSecurityService).passwordEncoder(bCryptPasswordEncoder()); 
    } 

    @Bean 
    public BCryptPasswordEncoder bCryptPasswordEncoder() { 
     return new BCryptPasswordEncoder(); 
    } 

    @Bean 
    public AuthenticationManager authenticationManager() throws Exception { 
     return super.authenticationManagerBean(); 
    } 
} 

Пользовательские Пользователь:

public class SecurityUser extends User { 

    private org.company.app.domain.User user; 

    public SecurityUser(org.company.app.domain.User user, 
         Collection<GrantedAuthority> grantedAuthorities) { 
     super(user.getEmail(),user.getPasswordEncoded(),grantedAuthorities); 
     this.user = user; 
    } 

    public org.company.app.domain.User getUser() { 
     return user; 
    } 

    public void setUser(org.company.app.domain.User user) { 
     this.user = user; 
    } 

    public Collection<Role> getRoles() { 
     return this.user.getRoles(); 
    } 

    @Override 
    public String toString() { 
     return MoreObjects.toStringHelper(this) 
       .add("user", user) 
       .toString(); 
    } 
} 

Фильтр:

@Service 
public class StatelessAuthenticationFilter extends GenericFilterBean { 

    private final TokenAuthenticationService tokenAuthenticationService; 

    @Inject 
    public StatelessAuthenticationFilter(TokenAuthenticationService tokenAuthenticationService) { 
     this.tokenAuthenticationService = tokenAuthenticationService; 
    } 

    @Override 
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, 
         FilterChain filterChain) throws IOException, ServletException { 
     Authentication authentication = tokenAuthenticationService.getAuthentication((HttpServletRequest) servletRequest); 
     SecurityContextHolder.getContext().setAuthentication(authentication); 
     filterChain.doFilter(servletRequest, servletResponse); 
     SecurityContextHolder.getContext().setAuthentication(null); 
    } 
} 

TokenAuthenticationService

@Service 
public class TokenAuthenticationService { 

    private static final String AUTH_HEADER_NAME = "X-AUTH-TOKEN"; 

    private final TokenHandler tokenHandler; 

    @Inject 
    public TokenAuthenticationService(TokenHandler tokenHandler) { 
     this.tokenHandler = tokenHandler; 
    } 

    public String addAuthentication(HttpServletResponse response, UserAuthentication authentication) { 
     final SecurityUser user = (SecurityUser) authentication.getDetails(); 
     String token = tokenHandler.createTokenForUser(user); 
     response.addHeader(AUTH_HEADER_NAME, token); 
     return token; 
    } 

    public Authentication getAuthentication(HttpServletRequest request) { 
     final String token = request.getHeader(AUTH_HEADER_NAME); 
     if (token != null) { 
      final SecurityUser user = tokenHandler.parseUserFromToken(token); 
      if (user != null) { 
       return new UserAuthentication(user); 
      } 
     } 
     return null; 
    } 
} 

TokenHandler:

@Service 
public class TokenHandler { 

    private Environment environment; 
    private final UserSecurityService userService; 
    private final String secret; 

    @Inject 
    public TokenHandler(Environment environment, UserSecurityService userService) { 
     this.environment = environment; 
     this.secret = this.environment.getRequiredProperty("application.security.secret"); 
     this.userService = userService; 
    } 

    public SecurityUser parseUserFromToken(String token) { 
     String username = Jwts.parser() 
       .setSigningKey(secret) 
       .parseClaimsJws(token) 
       .getBody() 
       .getSubject(); 
     return userService.loadUserByUsername(username); 
    } 

    public String createTokenForUser(SecurityUser user) { 
     return Jwts.builder() 
       .setSubject(user.getUsername()) 
       .signWith(SignatureAlgorithm.HS512, secret) 
       .compact(); 
    } 
} 

Реализация интерфейса аутентификации Spring Security

public class UserAuthentication implements Authentication { 

    private final SecurityUser user; 
    private boolean authenticated = true; 

    public UserAuthentication(SecurityUser user) { 
     this.user = user; 
    } 

    @Override 
    public Collection<? extends GrantedAuthority> getAuthorities() { 
     return user.getAuthorities(); 
    } 

    @Override 
    public Object getCredentials() { 
     return user.getPassword(); 
    } 

    @Override 
    public Object getDetails() { 
     return user; 
    } 

    @Override 
    public Object getPrincipal() { 
     return user.getUsername(); 
    } 

    @Override 
    public boolean isAuthenticated() { 
     return authenticated; 
    } 

    @Override 
    public void setAuthenticated(boolean b) throws IllegalArgumentException { 
     this.authenticated = b; 
    } 

    @Override 
    public String getName() { 
     return user.getUsername(); 
    } 
} 

Наконец моя реализация интерфейса UserDetailsService

@Service 
public class UserSecurityService implements UserDetailsService { 

    private static final Logger logger = LoggerFactory.getLogger(UserSecurityService.class); 

    private UserService userService; 

    @Inject 
    public UserSecurityService(UserService userService) { 
     this.userService = userService; 
    } 

    private final AccountStatusUserDetailsChecker detailsChecker = new AccountStatusUserDetailsChecker(); 

    @Override 
    public SecurityUser loadUserByUsername(String s) throws UsernameNotFoundException { 

     logger.debug("Attempting authentication with identifier {}", s); 

     User user = userService.getUserByUserName(s); 
     if (user == null) { 
      throw new UsernameNotFoundException(String.format("User with identifier %s was not found",s)); 
     } 

     Collection<GrantedAuthority> authorities = new HashSet<>(); 
     for (Role role : user.getRoles()) { 
      authorities.add(new SimpleGrantedAuthority(role.getSpringName())); 
     } 

     return new SecurityUser(user,authorities); 
    } 
} 
+0

вы решить эту проблему ?? – KJEjava48

ответ

0

Мы делаем в нашем проекте что-то подобное. Мы отправляем токен JWT как часть тела ответа. Клиент, который написан в AngularJS, берет маркер и сохраняет в памяти браузеров. Затем для всех последующих защищенных вызовов клиент вводит токен в заголовке запроса в качестве маркера-носителя. Наш JSON для аутентификации выглядит следующим образом:

{ 
    "username": "auser", 
    "password": "password", 
    "dbname": "data01" 
} 

и для каждого usiquent запроса мы добавим ниже в заголовке запроса

Bearer <token>