Spring Security and permissions system based JWT

One, Scene

Before and after the end of the separation, how to ensure the security of the data exchange?

Sb: Token Yeah

Moving end, applets, H5, etc. The client also JSON data transmission, identity verification problem is also related to

Second, the problem

Token in the end how to achieve, is the best way?

Who have been through one hundred projects (. (▼ understands ▼ メ) Loading force.) Has seen many such projects are implemented

  • token? we do not need
  • token-coded, and the background to the client (there are indeed many)
  • token dynamic, background generated by some algorithm token, provided to the client (in this way is not no, but not perfect)
  • Entire JSON data encrypted transmission, provide the key background (EM .... not evaluated)
  • and many more

Third, the solution

To explain today is the use of the JWT , Token solve the problem

# Science at JWT

JSON Web Token (JWT) is an information transfer between the network application JSON-based open standard (the RFC 7519) , as JSON object for securely transmitting information between different systems. The main usage scenario is generally used to provide and service providers who transfer between the authenticated user identity information in the identity.

JWT consists of three parts, the other as follows:

  • Header (header) contains two parts: token type and the signature algorithm
  • Payload (load) is carried Token custom content, data is base64, non-encryption, cracks, can not store sensitive information; more content, the longer the token
  • Signature (Signed) The Header + Payload composed of a string is calculated by the signature algorithm specified value to obtain a signature, the server can be obtained by this flag to determine whether the Token legitimate
# Explain Spring Security (Bonus)

There JWT Token solve the problem, combined with the Spring Security module to solve numerous user rights issues (really strong), of course, in addition to Spring Security, as well as Apache Shiro rights can be resolved, but there is no Security strong, the follow-up will write an article Detailed comparison two.

Fourth, implementation

pom.xml introduced Spring Security dependent and the jar JWT

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>
复制代码

JWT tools, Token generation, verification Token, and other refreshing Token

@Component
public class JwtTokenUtil {

    private static final String CLAIM_KEY_USERNAME = "sub";
    private static final String CLAIM_KEY_CREATED = "created";
    
    // 生成token
    public String generateToken(UserDetails userDetails) {
        ...
    }
    
    // 刷新token
    public String refreshToken(String token) {
        ...
    }
    
    // 校验token
    public Boolean validateToken(String token, UserDetails userDetails) {
        ...
    }
复制代码

token Token filter processing interface

@Component
public class JwtTokenFilter extends OncePerRequestFilter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Override
    protected void doFilterInternal (HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        String authHeader = request.getHeader(Constant.HEADER_STRING );
        if (authHeader != null && authHeader.startsWith(Constant.TOKEN_PREFIX )) {
            final String authToken = authHeader.substring(Constant.TOKEN_PREFIX.length() );
            String username = jwtTokenUtil.getUsernameFromToken(authToken);
            if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
                if (jwtTokenUtil.validateToken(authToken, userDetails)) {
                    UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
                            userDetails, null, userDetails.getAuthorities());
                    authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(
                            request));
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }
            }
        }
        chain.doFilter(request, response);
    }
}
复制代码

Spring Security Core Configuration

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true, securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsServiceImpl userService;

    @Bean
    public JwtTokenFilter authenticationTokenFilterBean() throws Exception {
        return new JwtTokenFilter();
    }

    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(new BCryptPasswordEncoder());
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        String[] urls = new String[]{"/user/login", "/user/register"};
        httpSecurity.csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests()
                // 允许注册和登录接口不需token访问
                .antMatchers(urls).permitAll()
                .anyRequest().authenticated();
        httpSecurity.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
        httpSecurity.headers().cacheControl();
    }
}
复制代码
Permissions test, the interface need to restrict access restrictions, add @PreAuthorize
@RestController
public class RoleController {

    /**
     * 测试普通权限
     *
     * @return
     */
    @PreAuthorize("hasAuthority('ROLE_NORMAL')")
    @GetMapping(value="/normal/test")
    public String test1() {
        return "普通角色访问";
    }

    /**
     * 测试管理员权限
     *
     * @return
     */
    @PreAuthorize("hasAuthority('ROLE_ADMIN')")
    @GetMapping(value = "/admin/test")
    public String test2() {
        return "管理员访问";
    }
}
复制代码

Users need to add roles to access, user role table as shown below

User Roles table

Fifth, test results

  • After a successful login return token

  • Without belt token, it will be denied access

  • Correct access method

In this source

Guess you like

Origin juejin.im/post/5d2c958ff265da1b667c0d34