1. Introduce dependencies

<! -- JJWT --> <dependency> <groupId> IO. Jsonwebtoken </groupId> <artifactId> JJWT </artifactId> <version>0.6.0</version> </dependency> <! --security--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency>Copy the code

2. Prepare the entity class

  • SysUser

/** id */ @Id private Integer id; /** password */ private String password; /** username */ private String username; /** / @transient private List<SysRole> roles;Copy the code
  • SysRole

   /** id */
    @Id
    private Integer id;
    /** name */
    private String name;
Copy the code
  • JwtUser

*/ @data public class JwtUser implements UserDetails {private static final Long serialVersionUID = -4959252432107932674L; private final long id; private final String username; private final String password; */ private final Collection<? extends GrantedAuthority> authorities; Public JwtUser(long id, String username, String password, Collection<? extends GrantedAuthority> authorities) { this.id = id; this.username = username; this.password = password; this.authorities = authorities; } @Override public Collection<? extends GrantedAuthority>getAuthorities() {
        return authorities;
    }

    @Override
    @JsonIgnore
    public String getPassword() {
        return password;
    }

    @Override
    public String getUsername() {
        return username;
    }

    @Override
    @JsonIgnore
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    @JsonIgnore
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    @JsonIgnore
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    @JsonIgnore
    public boolean isEnabled() {
        return true; }}Copy the code
  • JwtUserFactory

private JwtUserFactoryPublic static JwtUser create(SysUser user){returnnew JwtUser( user.getId(), user.getUsername(), user.getPassword(), map2GrantedAuthorities(user.getRoles()) ); } /** * private static List<GrantedAuthority> map2GrantedAuthorities(List<SysRole> authorities){return authorities.stream()
                .map(e -> role2SimpleGrantedAuthority(e))
                .collect(Collectors.toList());
    }

    private static SimpleGrantedAuthority role2SimpleGrantedAuthority(SysRole role){
        return new SimpleGrantedAuthority(role.getName());
    }
Copy the code

3. Implement the UserDetailService interface

@Override public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { SysUser sysUser = userRepository.findByUserName(s); // Call the persistence layer to get user information from the databaseif (sysUser == null)
            throw new UsernameNotFoundException("User name does not exist"); List<SysRole> roles = sysRoleRepository.findRolesByUserId(sysUser.getId()); // Based on the user ID or user permission listif (CollectionUtils.isEmpty(roles))
            roles = Collections.emptyList();
        sysUser.setRoles(roles);
        return JwtUserFactory.create(sysUser);
    }
Copy the code

4. The server cannot use session control because the front end is separated from the back end. Before the Security filter starts, obtain the TOKEN of the HEADER from the JWT and verify the token in the JWT

  • Front JWT filter for security
@Component @Slf4j public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { /** * Autowired Private UserDetailsService customUserService; @Value("${jwt.header}")
    private String tokenHeader;

    @Value("${jwt.tokenHead}")
    private String tokenHead;


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { String authHeader = request.getHeader(this.tokenHeader); / / get the headerif(authHeader ! = null && AuthHeader. startsWith(tokenHead)) {// Determine header final String authToken = authHeader.substring(tokenHead.length()); // The part after"Bearer "
            if(JwtUtil.getClaim(authToken) ! String username = jwtutil.getClaim (authToken).getSubject(); // Retrieves information from JWT; Claims logger.info(Claims logger.info)"checking authentication " + username);

                if(username ! = null && SecurityContextHolder.getContext().getAuthentication() == null) { UserDetails userDetails = this.customUserService.loadUserByUsername(username); // Put the validation information into SecurityContextHolder, UsernamePasswordAuthenticationToken is account password Security validation tool class UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( userDetails, null, userDetails.getAuthorities()); authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails( request)); logger.info("authenticated user " + username + ", setting security context"); SecurityContextHolder.getContext().setAuthentication(authentication); } } } chain.doFilter(request, response); }}Copy the code
  • This is the key
// Put the validation information into SecurityContextHolder, UsernamePasswordAuthenticationToken is account password Security validation tool class UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( userDetails, null, userDetails.getAuthorities()); authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails( request)); logger.info("authenticated user " + username + ", setting security context");
                    SecurityContextHolder.getContext().setAuthentication(authentication);
Copy the code
  • JWT tools
Public static Claims getClaim(String token){try {Claims = jwts.parser ().setSigningKey()"abcdefg")
                    .parseClaimsJws(token).getBody();
            return claims;
        }catch (Exception e){
            returnnull; }} /** * Set user information to JWT */ public static StringsetClaim(String subject){
        String token = Jwts
                .builder()
                .setSubject(subject)
                .setIssuedAt(new Date())
                .signWith(SignatureAlgorithm.HS256, "abcdefg")
                .compact();
        return token;
    }
Copy the code

5 Security configuration

@ Configuration @ EnableWebSecurity / / open the WebSecurity support @ EnableGlobalMethodSecurity (prePostEnabled =true) / / open prePostEnabled annotation support public class WebSecurityConfig extends WebSecurityConfigurerAdapter {@autowired private UserDetailsService jwtUserDetailsServiceImpl; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth .userDetailsService(jwtUserDetailsServiceImpl) .passwordEncoder(passwordEncoder()); } /** * password encrypted bean, using BCrypt * @return
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        returnnew BCryptPasswordEncoder(); } /** * prefilter * @return
     */
    @Bean
    JwtAuthenticationTokenFilter authenticationTokenFilterBean() {returnnew JwtAuthenticationTokenFilter(); } @override protected void configure(HttpSecurity HTTP) throws Exception {http.csrf ().disable() // Disables CSRF protection SessionManagement (.) sessionCreationPolicy (sessionCreationPolicy. STATELESS) / / disable session. And (). AuthorizeRequests () // All requests are validated. AntMatchers ("/auth/**").permitall () // Login registration request filter.antmatchers ("/"."/*.html"."/favicon.ico"."/**/*.html"."/**/*.js"."/**/*.css").permitall () // Static resource filter.anyRequest ().fullyauthenticated (). And ().ExceptionHandling () // Validate failed configurations .authenticationEntryPoint(new RestAuthenticationEntryPoint()) ; HTTP / / add a profiteer. AddFilterBefore (authenticationTokenFilterBean (), UsernamePasswordAuthenticationFilter. Class); HTTP // Disable header.cache.headers ().cachecontrol (); }}Copy the code

6.RestAuthenticationEntryPoint

/** * Implement instantiation entrypoint custom method fails method * Created by gaowenfeng on 2017/8/9. */ public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, Message in ServletException {/ / capture AuthenticationException and encapsulated into a custom exception thrown response. SetCharacterEncoding ("utf-8"); response.getWriter().write( new Result().setCode(ResultCode.UNAUTHORIZED).setMessage(AuthErrorEnum.AUTH_HEADER_ERROR.getMessage()).toString()); }}Copy the code

7. Log on to the service

@Override
    public String login(String username, String password) {
        UsernamePasswordAuthenticationToken upToken = new UsernamePasswordAuthenticationToken(username, password);
        final Authentication authentication = authenticationManager.authenticate(upToken);
        SecurityContextHolder.getContext().setAuthentication(authentication);

        final UserDetails userDetails = userDetailsService.loadUserByUsername(username);
        final String token = JwtUtil.setClaim(username);
        return token;
    }
Copy the code

8. Log on to the controller

@RequestMapping(value = "/auth/login", method = RequestMethod.GET) public ResponseEntity<? > refreshAndGetAuthenticationToken( HttpServletRequest request){ String token = request.getHeader(tokenHeader); String refreshedToken = authService.refresh(token);if(refreshedToken == null) {
            return ResponseEntity.badRequest().body(null);
        } else {
            returnResponseEntity.ok(refreshedToken); }}Copy the code

9. Include your Github address at the end

Github.com/MarkGao1152…