简体   繁体   中英

How can i display User-specific data after authentication

I have 2 microservices. An API gateway with a JWT authentication and a microservice that manages templates from the respective user. My goal is that the user can only see his templates. But I am not clear how I do it. Do I have to generate an additional ID token or can I also solve the problem with 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);

    }

This is my get method to be able to display the respective template. However, I don't want the user's name to be required in REST.After the authentication it should be possible to use the token to be able to output user-specific data or? I also have two database tables. One for authentication and one for templates. In the authentication table, I once have the data username and password as well as a name of the user. In the template table I only have the name of the user (to keep the table small). This means that in the case of a get request from templates, the name of the user must be requested from the authentication microservice in order to be able to display only the templates of the user. Can someone tell me which technology I work best with?

@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;
    }

}

If you're using Spring and JWT for generating tokens, then you can add token enhancers to your JWT, token enhancers allow you to add additional information to your token.

Then you can add the username or user id to your token.

In your call to your template endpoint you can remove the name part of your url. and rely on the received token to get the username.

You can find here how to add token enhancers https://www.baeldung.com/spring-security-oauth-jwt

You want to fetch some user data from his JWT token, so you need to add some extra information to user token when you're generating it, for this purpose you must use a custom TokenEnhancer .

This post might be useful for your scenario :

Can-i-include-user-information-while-issuing-an-access-token

In summary

  1. Create CustomTokenEnhancer

  2. Add CustomTokenEnhancer to AuthorizationServerConfigurerAdapter as a bean

  3. Get saved data from token and use it (In the controller ,...)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM