Zuul integration with Spring Security JWT

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/h_sn9999/article/details/102692108

JSON Web Token (JWT) is the most popular cross-domain authentication solutions in the micro-environment services, we can help implement authentication server JWT

The basic process is as shown below:

 

JWT principle that after server authentication, generates a JSON object and sends it back to the user, as shown below.

{

"UserName": "xxx",

"Role": "Admin,User",

"Expire": "2019-06-01 10:13:26"

}

Thereafter, when the user communications with the server, the client in the request is sent back JSON object. Server depends only on the JSON object to identify the user. To prevent users from tampering with the data, a signature server (for details, see below) was added to generate objects.

The server does not save any session data, i.e., becomes stateless server, making it easier to expand.

 

The project is divided into several modules

        <module>spc-zuul-gateway</module>
        <module>base-framwork-jwt</module>
        <module>spc-auth-center</module>

 

The key code is as follows:

//扩展 Spring security 的 AbstractAuthenticationProcessingFilter
public class JwtUsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    private final JwtAuthenticationConfig config;
    private final ObjectMapper mapper;
    private AuthenticationSuccessHandler successHandler = new SavedRequestAwareAuthenticationSuccessHandler();

    public JwtUsernamePasswordAuthenticationFilter(JwtAuthenticationConfig config, AuthenticationManager authManager) {
        super(new AntPathRequestMatcher(config.getUrl(), "POST"));
        setAuthenticationManager(authManager);
        this.config = config;
        this.mapper = new ObjectMapper();
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse rsp)
            throws AuthenticationException, IOException {
        String username= req.getParameter("username");
        String password= req.getParameter("password");
        
        User u = new User();
        u.setUsername(username);
        u.setPassword(password);
        return getAuthenticationManager().authenticate(new UsernamePasswordAuthenticationToken(
                u.getUsername(), u.getPassword(), Collections.emptyList()
        ));
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest req, HttpServletResponse rsp, FilterChain chain,
                                            Authentication auth) throws IOException, ServletException {
        Instant now = Instant.now();
        String token = Jwts.builder()
                .setSubject(auth.getName())
                .claim("authorities", auth.getAuthorities().stream()
                        .map(GrantedAuthority::getAuthority).collect(Collectors.toList()))
                .setIssuedAt(Date.from(now))
                .setExpiration(Date.from(now.plusSeconds(config.getExpiration())))
                .signWith(SignatureAlgorithm.HS256, config.getSecret().getBytes())
                .compact();
        rsp.addHeader(config.getHeader(), config.getPrefix() + " " + token);
        
        SecurityContextHolder.getContext().setAuthentication(auth);
        successHandler.onAuthenticationSuccess(req, rsp, auth);
    }

 

Add custom filter chain in the authentication server JwtUsernamePasswordAuthenticationFilter


@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    JwtAuthenticationConfig config;

    @Bean
    public JwtAuthenticationConfig jwtConfig() {
        return new JwtAuthenticationConfig();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
        auth.inMemoryAuthentication().withUser("admin").password(encoder.encode("admin")).roles("ADMIN", "USER").and()
                .withUser("hsn").password(encoder.encode("hsn")).roles("USER");
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity.csrf().disable().logout().disable()
                .addFilterBefore(new JwtUsernamePasswordAuthenticationFilter(config, authenticationManager()),
                        UsernamePasswordAuthenticationFilter.class)

                .authorizeRequests().antMatchers("/").permitAll()
                .antMatchers("/user/**").hasRole("USER")
                .and()
                .formLogin().loginPage("/login").defaultSuccessUrl("/user")
                .and()
                .logout().logoutUrl("/logout")
                .logoutSuccessUrl("/login");
    }
}

When the user logs on, will remain in the return header authentication information, visit initiated each time, Zuul only needs to be validated token, so for permission before calling back-end service verification

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private JwtAuthenticationConfig config;

    @Bean
    public JwtAuthenticationConfig jwtConfig() {
        return new JwtAuthenticationConfig();
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                .csrf().disable()
                .logout().disable()
                //.formLogin().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                    .anonymous()
                .and()
                    .exceptionHandling().authenticationEntryPoint(
                            (req, rsp, e) -> rsp.sendError(HttpServletResponse.SC_UNAUTHORIZED))
                .and()
                    .addFilterAfter(new JwtTokenAuthenticationFilter(config),
                            UsernamePasswordAuthenticationFilter.class)
                .authorizeRequests()
                    .antMatchers(config.getUrl()).permitAll()
                    //.antMatchers("/swagger-ui.html").permitAll()
                    .antMatchers("/static/**").permitAll()
                    .antMatchers("/oauth/rest_token*").permitAll()
                    .antMatchers("/login*").permitAll()

                    .antMatchers("/user/**").hasAnyRole("ADMIN")
                    .antMatchers("/order/order/placeOrder/**").hasRole("ADMIN")
                    .antMatchers("/order/user").hasRole("USER")
                    .antMatchers("/order/guest").permitAll()
                    .antMatchers("/login*").anonymous();
                    
                    
                    
        //httpSecurity.authenticationProvider();
                 
        
    }
}
 

testing method:

After starting the service, click on the login input admin / admin login is successful, you can see the head in return authentication information, this information can be put on the next call

 

Please refer to the complete code: https://github.com/hsn999/start-cloud

 

Guess you like

Origin blog.csdn.net/h_sn9999/article/details/102692108