Mymes authentication and authorization by Integrating SpringBoot with JWT

Article after article, configuration class dependencies and method descriptions for SpringSecurity

  • Configure (HttpSecurity HttpSecurity): for blocking URL paths, JWT filtering, and exception handling

  • Configure (AuthenticationManagerBuilder auth) : used to configure userDetailsService and PasswordEncoder

  • JwtAuthenticationTokenFilter: add filter before a user name and password, if have a token, depending on the token to login

  • RestfulAccessDeniedHandler: when users do not have access to, return the JSON format

  • RestAuthenticationEntryPoint: under the condition of token failure or not logged in, return the JSON format

  • PasswordEncoder: An interface defined by SpringSecurity to encode and compare passwords. Currently, BCryptPasswordEncoder is used.

  • IgnoreUrlsConfig: Used to get unsecured resource paths from application.yml

  • UserDetailsService: SpringSecurity core interface, get the user information

Add IgnoreUrlsConfig

package com.cn.mymes.utils.config; / *

 *Created by zbb on 2021/1/6

* * /



import lombok.Getter;

import lombok.Setter;

import org.springframework.boot.context.properties.ConfigurationProperties;



import java.util.ArrayList;

import java.util.List;



/ * *

* Used to configure resource paths that do not need protection

 *

* /

@Getter

@Setter

@ConfigurationProperties(prefix = "secure.ignored")

public class IgnoreUrlsConfig {



    private List<String> urls = new ArrayList<>();



}



Copy the code

Configure resource paths that do not need security protection under application.yml

secure:

  ignored:

    urls: # Secure path whitelist

      - /swagger-ui.html

      - /swagger-resources/**

      - /swagger/**

      - /**/v2/api-docs

      - /**/*.js

      - /**/*.css

      - /**/*.png

      - /**/*.ico

      - /webjars/springfox-swagger-ui/**

      - /actuator/**

      - /druid/**

      - /admin/login

      - /admin/register

      - /admin/info

      - /admin/logout

Copy the code

Add a Token filter JwtAuthenticationTokenFilter

package com.cn.mymes.component;



import com.cn.mymes.utils.JwtTokenUtil;

import org.slf4j.Logger;

import org.slf4j.LoggerFactory;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.beans.factory.annotation.Value;

import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;

import org.springframework.security.core.context.SecurityContextHolder;

import org.springframework.security.core.userdetails.UserDetails;

import org.springframework.security.core.userdetails.UserDetailsService;

import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;

import org.springframework.web.filter.OncePerRequestFilter;



import javax.servlet.FilterChain;

import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

/ * *

* Token login filter

 *

* /

public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    private static final Logger LOGGER = LoggerFactory.getLogger(JwtAuthenticationTokenFilter.class);

    @Autowired

    private UserDetailsService userDetailsService;

    @Autowired

    private JwtTokenUtil jwtTokenUtil;

    @Value("${jwt.tokenHeader}")

    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);

        if(authHeader ! = null && authHeader.startsWith(this.tokenHead)) {

String authToken = authHeader.substring(this.tokenHead.length()); // The part after"Bearer "

            String username = jwtTokenUtil.getUserNameFromToken(authToken);

            LOGGER.info("checking username:{}", username);

            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));

                    LOGGER.info("authenticated user:{}", username);

                    SecurityContextHolder.getContext().setAuthentication(authentication);

                }

            }

        }

        chain.doFilter(request, response);

    }

}

Copy the code

Add the right to access RestfulAccessDeniedHandler method

package com.cn.mymes.component;



import cn.hutool.json.JSONUtil;

import com.cn.mymes.common.CommonResult;

import org.springframework.security.access.AccessDeniedException;

import org.springframework.security.web.access.AccessDeniedHandler;



import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

/ * *

* Returns custom JSON format results when no permission is available

* /

public class RestfulAccessDeniedHandler implements AccessDeniedHandler{

    @Override

    public void handle(HttpServletRequest request,

                       HttpServletResponse response,

                       AccessDeniedException e) throws IOException, ServletException {

        response.setHeader("Access-Control-Allow-Origin"."*");

        response.setHeader("Cache-Control"."no-cache");

        response.setCharacterEncoding("UTF-8");

        response.setContentType("application/json");

        response.getWriter().println(JSONUtil.parse(CommonResult.forbidden(e.getMessage())));

        response.getWriter().flush();

    }

}

Copy the code

Add login failed to login or overdue return custom results RestAuthenticationEntryPoint method

package com.cn.mymes.component;





import cn.hutool.json.JSONUtil;

import com.cn.mymes.common.CommonResult;

import org.springframework.security.core.AuthenticationException;

import org.springframework.security.web.AuthenticationEntryPoint;



import javax.servlet.ServletException;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import java.io.IOException;

/ * *

* If you have not logged in or the login has expired, the custom JSON format is returned

* /

public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {

    @Override

    public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {

        response.setHeader("Access-Control-Allow-Origin"."*");

        response.setHeader("Cache-Control"."no-cache");

        response.setCharacterEncoding("UTF-8");

        response.setContentType("application/json");

        response.getWriter().println(JSONUtil.parse(CommonResult.unauthorized(authException.getMessage())));

        response.getWriter().flush();

    }

}

Copy the code

Add the SpringSecurity core interface to obtain user information

package com.cn.mymes.domain;









import com.cn.mymes.mgb.model.UmsAdmin;

import com.cn.mymes.mgb.model.UmsResource;

import org.springframework.security.core.GrantedAuthority;

import org.springframework.security.core.authority.SimpleGrantedAuthority;

import org.springframework.security.core.userdetails.UserDetails;



import java.util.Collection;

import java.util.List;

import java.util.stream.Collectors;



/ * *

* SpringSecurity core, get user information

 *

* /

public class AdminUserDetails implements UserDetails {

    private UmsAdmin umsAdmin;

    private List<UmsResource> resourceList;

    public AdminUserDetails(UmsAdmin umsAdmin, List<UmsResource> resourceList) {

        this.umsAdmin = umsAdmin;

        this.resourceList = resourceList;

    }



    @Override

    public Collection<? extends GrantedAuthority> getAuthorities() {

// Returns the role of the current user

        return resourceList.stream()

                .map(role ->new SimpleGrantedAuthority(role.getId()+":"+role.getName()))

                .collect(Collectors.toList());

    }



    @Override

    public String getPassword() {

        return umsAdmin.getPassword();

    }



    @Override

    public String getUsername() {

        return umsAdmin.getUsername();

    }



    @Override

    public boolean isAccountNonExpired() {

        return true;

    }



    @Override

    public boolean isAccountNonLocked() {

        return true;

    }



    @Override

    public boolean isCredentialsNonExpired() {

        return true;

    }



    @Override

    public boolean isEnabled() {

        return umsAdmin.getStatus().equals(1);

    }

}

Copy the code

Tomorrow we will talk about the implementation of the dynamic management part of the SpringSecurity project authority management in MyMes

No. The public https://mp.weixin.qq.com/s/nfat2WWWUXdmfUGFBAVEuA