java - 身份验证后如何显示用户特定数据

标签 java microservices

我有 2 个微服务。具有 JWT 身份验证的 API 网关和管理各个用户模板的微服务。我的目标是用户只能看到他的模板。但我不清楚我是如何做到的。我是否必须生成额外的 ID token ,或者我也可以使用 feign 解决问题吗?

@GetMapping("/templates/{name}/{template_id}")
    public Template retrieveTemplate(@PathVariable("name") String name,@PathVariable("template_id") int template_id)
    {
        return templateRepository.findByTemplateIdAndName(template_id, name);

    }

这是我的获取方法,能够显示相应的模板。但是,我不希望 REST 中需要用户名。身份验证后,应该可以使用 token 来输出用户特定的数据,或者?我还有两个数据库表。一种用于身份验证,一种用于模板。在身份验证表中,我曾经拥有数据用户名和密码以及用户名。在模板表中,我只有用户名(以保持表较小)。这意味着,在从模板获取请求的情况下,必须从身份验证微服务请求用户的名称,以便能够仅显示用户的模板。有人可以告诉我哪种技术最适合我吗?

@Service
public class JwtUtil {

        private String SECRET_KEY = "helloworld";

        public String extractUsername(String token)
        {
            return extractClaim(token, Claims::getSubject);
        }
        public Date extractExpiration(String token)
        {
            return extractClaim(token, Claims::getExpiration);
        }
        public <T> T extractClaim(String token, Function<Claims,T> claimsResolver)
        {
            final Claims claims = extractAllClaims(token);
            return claimsResolver.apply(claims);
        }
        private Claims extractAllClaims(String token)
        {
            return Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();
        }
        private Boolean isTokenExpired(String token)
        {
            return extractExpiration(token).before(new Date());
        }
        public String generateToken(UserDetails userDetails)
        {
            Map<String,Object> claims =new HashMap<>();
            return createToken(claims,userDetails.getUsername());
        }
        private String createToken(Map<String, Object> claims, String subject)
        {
            return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
                    .setExpiration(new Date(System.currentTimeMillis() + 1000*60*60*24*360))
                    .signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact();
        }
        public Boolean validateToken(String token, UserDetails userDetails)
        {
            final String username = extractUsername(token);
            return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
        }
}

package sendMessage.LoginJwtAPIGateway;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@EnableWebSecurity
public class SecurityConfigurer extends WebSecurityConfigurerAdapter{

    @Autowired
    private MyUserDetailsService myUserDetailsService;

    @Autowired
    private JwtRequestFilter jwtRequestFilter;

    @Autowired
    UserDetailsService userDetailsService;

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

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
            .authorizeRequests().antMatchers("/authenticate").permitAll().
            antMatchers("/users").hasRole("ADMIN")
            .anyRequest().authenticated()
            .and().sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        http.addFilterBefore(jwtRequestFilter,  UsernamePasswordAuthenticationFilter.class);
    }
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception
    {
        return super.authenticationManagerBean();
    }


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

}
@Component
public class JwtRequestFilter extends OncePerRequestFilter{

    @Autowired
    private MyUserDetailsService userDetailsService;
    @Autowired
    private JwtUtil jwtUtil;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException {

        final String authorizationHeader =request.getHeader("Authorization");

        String username = null;
        String jwt = null;

        if(authorizationHeader !=null && authorizationHeader.startsWith("Bearer "))
        {
            jwt = authorizationHeader.substring(7);
            username= jwtUtil.extractUsername(jwt);
        }
        if (username != null && SecurityContextHolder.getContext().getAuthentication()==null)
        {
            UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);

            if (jwtUtil.validateToken(jwt,  userDetails))
            {
                UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
                userDetails, null, userDetails.getAuthorities());
                usernamePasswordAuthenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
            }
        }
        chain.doFilter(request,response);
    }

}
package sendMessage.LoginJwtAPIGateway;

import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

public class MyUserDetails implements UserDetails{

    private String username;
    private String password;
    private boolean active;
    private List<GrantedAuthority> authorities;


    public MyUserDetails()
    {

    }

    public MyUserDetails(User user) {
        this.username=user.getUsername();
        this.password=user.getPassword();
        this.active=user.isActive();
        this.authorities =Arrays.stream(user.getRoles().split(","))
                .map(SimpleGrantedAuthority::new)
                .collect(Collectors.toList());

    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        // TODO Auto-generated method stub
        return authorities;
    }

    @Override
    public String getPassword() {
        // TODO Auto-generated method stub
        return password;
    }

    public String getUsername() {
        // TODO Auto-generated method stub
        return username;
    }

    @Override
    public boolean isAccountNonExpired() {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public boolean isEnabled() {
        // TODO Auto-generated method stub
        return active;
    }

}

最佳答案

如果您使用 Spring 和 JWT 生成 token ,那么您可以向 JWT 添加 token 增强器, token 增强器允许您向 token 添加其他信息。

然后您可以将用户名或用户 ID 添加到您的 token 中。

在调用模板端点时,您可以删除网址的名称部分。并依靠收到的 token 来获取用户名。

您可以在此处找到如何添加 token 增强器 https://www.baeldung.com/spring-security-oauth-jwt

关于java - 身份验证后如何显示用户特定数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59982273/

相关文章:

rabbitmq - 微服务为什么要使用RabbitMQ?

node.js - 微服务、API 网关和前端

java - Android检测语音识别语言

java - 如何使用 Spring "matches"方法检查旧密码?

java - (Java) 将数字字符串转换为整数数组

django - Docker中的Django微服务

Spring ControllerAdvice - 无法覆盖 ResponseEntityExceptionHandler 中的 handleHttpRequestMethodNotSupported()

azure - 从 Internet 访问 Service Fabric

java - Azure 存储 Java API : Check if storage account support secure transfer or not using java SDK

java - 为什么这个时区设置不正确?