首页 > 解决方案 > 如何使用在层微服务中生成的令牌返回 HttpResponse

问题描述

向上!编辑:也许我的问题不够清楚:我的 API Web 控制器的控制器中的 HttpResponse 似乎不包含我在 MS-Authentication 中放入的 cookie 或 Jwt 令牌。我认为问题可能出在我在代理接口中声明的方法中。我需要什么样的回报才能更新我的回复?

我有一个微服务“身份验证”,一个带有 Zuul 的网关和一个 Api Web。

我使用 Spring Boot 安全性实现了 jwt 令牌安全性。

当我的用户尝试从 api web 登录时,用户名和密码被发送到 MS-Authentication(Zuul 配置为允许任何人调用此 MS),并且在验证用户在数据库中之后,它会生成一个令牌。

我的问题是我无法取回带有令牌的响应(或 cookie,我尝试将令牌放入 cookie 并添加 cookie 作为响应)。

这是我第一个使用 Spring Boot 和微服务的项目!

当我不使用 Api 并使用 postmann 进行测试时,令牌很好地返回响应!

这是我的代码:Api-web 中的 LoginController

@Controller
public class LoginController {

    private final BookProxy bookProxy;

    @Autowired
    public LoginController(BookProxy bookProxy) {
        this.bookProxy = bookProxy;
    }

    @GetMapping("/login")
    public String loginForm(Model model){

        model.addAttribute("user",new UserBean());

        return "login";

    }

    @PostMapping("/login")
    public String doLogin(@ModelAttribute UserBean user){

        bookProxy.authenticateClient(user);

        return "Home";
    }   
}

Api-web 中的代理

@FeignClient(name = "zuul-server", url = "localhost:8762") 
public interface Proxy {

    /* Login */
    @PostMapping("/auth/login")
    void authenticateClient(@RequestBody UserBean user);
}

Zuul 网关中的 SecurityConfig

@EnableWebSecurity
public class SecurityTokenConfig extends WebSecurityConfigurerAdapter {

    // Roles
    private static final String ADMIN = "ADMIN";
    private static final String EMPLOYEE = "EMPLOYEE";
    private static final String CLIENT = "CLIENT";

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .addFilterAfter(new JwtTokenAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
                .authorizeRequests()
                .antMatchers("/auth/**").permitAll()
                .antMatchers("/book/**").hasAnyRole(ADMIN,EMPLOYEE)
                .anyRequest().authenticated();
    }

}

MS-Authentication 中的 SecurityConfig

@EnableWebSecurity
public class SecurityCredentialsConfig extends WebSecurityConfigurerAdapter {

    private final UserPrincipalDetailsService userPrincipalDetailsService;

    @Autowired
    public SecurityCredentialsConfig(UserPrincipalDetailsService userPrincipalDetailsService) {
        this.userPrincipalDetailsService = userPrincipalDetailsService;
    }

    // Roles
    private static final String ADMIN = "ADMIN";
    private static final String EMPLOYEE = "EMPLOYEE";
    private static final String CLIENT = "CLIENT";


    @Override
    protected void configure(AuthenticationManagerBuilder auth){
        auth
                .authenticationProvider(authenticationProvider());
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()         
                .addFilter(new JwtUsernameAndPasswordAuthenticationFilter(authenticationManager()))
                .authorizeRequests()
                .antMatchers(HttpMethod.POST,"/auth/Login").permitAll()
                .antMatchers("/book/consult/**").hasAnyRole(ADMIN,EMPLOYEE)
                .antMatchers("/book/**").hasAnyRole(ADMIN,EMPLOYEE)
                .anyRequest().authenticated();
    }

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

    @Bean
    DaoAuthenticationProvider authenticationProvider(){

        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
        daoAuthenticationProvider.setUserDetailsService(userPrincipalDetailsService);

        return daoAuthenticationProvider;

    }

}

过滤谁在 MS-Authentication 中对用户进行身份验证并生成令牌

public class JwtUsernameAndPasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    private Logger log = LoggerFactory.getLogger(this.getClass());

    // We use auth manager to validate the user credentials
    private AuthenticationManager authManager;


    JwtUsernameAndPasswordAuthenticationFilter(AuthenticationManager authManager) {
        this.authManager = authManager;

        // By default, UsernamePasswordAuthenticationFilter listens to "/login" path.
        // I use "/auth" path so i need to override the defaults.
        this.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher(JwtConfig.URI, "POST"));
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException {

        // Grab credentials and map them to login viewmodel
        LoginViewModel credentials = null;
        try {
            credentials = new ObjectMapper().readValue(request.getInputStream(), LoginViewModel.class);
        } catch (IOException e) {
            log.error(e.getMessage());
        }

        // Create login token
        assert credentials != null;
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
                credentials.getUsername(),
                credentials.getPassword(),
                new ArrayList<>());

        // Return authenticate user
            return authManager.authenticate(authenticationToken);
    }

    // Upon successful authentication, generate a token.
    // The 'auth' passed to successfulAuthentication() is the current authenticated user.
    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
                                            Authentication auth) throws IOException, ServletException {

        // Grab principal
        UserPrincipal principal = (UserPrincipal) auth.getPrincipal();


        String token = JWT.create()
                //.withHeader(headerClaims)
                .withClaim("role","ROLE_" + principal.getRole())
                .withSubject(principal.getUsername())
                .withExpiresAt(new Date(System.currentTimeMillis() + JwtConfig.EXPIRATION))
                .sign(HMAC512(JwtConfig.SECRET.getBytes()));

        // ADD COOKIES
        Cookie cookie = new Cookie(JwtConfig.HEADER, token);
        cookie.setSecure(false);
        cookie.setHttpOnly(true);
        cookie.setMaxAge(999999);
        cookie.setDomain("localhost");
        cookie.setPath("/");

        // Add token and cookie in response (try both)
        response.addHeader(JwtConfig.HEADER, JwtConfig.PREFIX + token);
        response.addCookie(cookie);

    }

}

Jwt 配置常量

public class JwtConfig {

    public static final String URI = "/auth/**";
    public static final String HEADER = "Authorization";
    public static final String PREFIX = "Bearer ";
    public static final int EXPIRATION = 24*60*60;
    public static final String SECRET = "JwtSecretKey";

}

标签: javarestspring-securityjwtmicroservices

解决方案


推荐阅读