如何使用在微服务层中生成的令牌返回HttpResponse

时间:2019-12-10 19:34:08

标签: java rest spring-security jwt microservices

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

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

我通过Spring Boot安全性实现了jwt令牌安全性。

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

我的问题是我无法获得令牌内部的响应(或cookie,我试图将令牌放入cookie并添加cookie作为响应)。

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

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

这是我的代码: Api网站中的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网络中的代理

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

}

0 个答案:

没有答案