Я создаю 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);
}
}
вы решить эту проблему ?? – KJEjava48