Utilisation de Spring Security et de JWT pour obtenir l'authentification et l'autorisation mymes (2)

SpringBoot intègre Spring Security et JWT pour obtenir l'authentification et l'autorisation mymes (2)

Suite de l'article précédent, les dépendances liées à la classe de configuration de SpringSecurity et la description de la méthode

  • configure (HttpSecurity httpSecurity): utilisé pour intercepter le chemin de l'url, le filtrage JWT et la gestion des exceptions
  • configure (AuthenticationManagerBuilder auth): utilisé pour configurer userDetailsService et PasswordEncoder
  • JwtAuthenticationTokenFilter: Ajoutez un filtre avant le nom d'utilisateur et le mot de passe. S'il y a un token, il se connectera en fonction du token.
  • RestfulAccessDeniedHandler: lorsque l'utilisateur n'a pas de droits d'accès, retourne le résultat du traitement au format JSON
  • RestAuthenticationEntryPoint: en cas d'échec du jeton ou d'absence de connexion, retournez le résultat du traitement au format JSON
  • PasswordEncoder: l'interface définie par SpringSecurity pour coder et comparer les mots de passe. Actuellement, BCryptPasswordEncoder est utilisé;
  • IgnoreUrlsConfig: utilisé pour obtenir des chemins de ressources qui ne nécessitent pas de protection de sécurité depuis application.yml
  • UserDetailsService: interface principale de SpringSecurity pour obtenir des informations utilisateur

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

/**
 * 用于配置不需要保护的资源路径
 *
 */
@Getter
@Setter
@ConfigurationProperties(prefix = "secure.ignored")
public class IgnoreUrlsConfig {

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

}

Configurer les chemins de ressources qui ne nécessitent pas de protection de sécurité dans application.yml

secure:
  ignored:
    urls: #安全路径白名单
      - /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

Ajouter un filtre de jeton 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登录过滤器
 *
 */
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);
    }
}

Ajouter la méthode RestfulAccessDeniedHandler lorsqu'il n'y a pas d'accès

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;
/**
 *在没有权限访问时,返回自定义JSON格式结果
 */
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();
    }
}

Ajoutez la méthode RestAuthenticationEntryPoint qui renvoie un résultat personnalisé qui n'est pas connecté ou a expiré

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;
/**
 * 未登录或者登录过期时,返回自定义JSON格式
 */
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();
    }
}

Ajouter l'interface principale de SpringSecurity pour obtenir des informations utilisateur

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核心,获取用户信息
 *
 */
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() {
        //返回当前用户的角色
        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);
    }
}

Demain, je parlerai de l'implémentation de la partie gestion dynamique de la gestion de l'autorité de projet Spring Security dans MyMes

le public

Utilisation de Spring Security et de JWT pour obtenir l'authentification et l'autorisation mymes (2)

Je suppose que tu aimes

Origine blog.51cto.com/15077535/2593739
conseillé
Classement