Maison  >  Article  >  Java  >  Comment SpringBoot combine JWT pour implémenter le contrôle des autorisations de connexion

Comment SpringBoot combine JWT pour implémenter le contrôle des autorisations de connexion

WBOY
WBOYavant
2023-05-20 11:01:061156parcourir

Nous devons d'abord importer le package jwt utilisé :

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.8.0</version>
</dependency>

<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.2.0</version>
</dependency>

1. Préparer LoginUser (stocker les informations de connexion de l'utilisateur) et JwtUser

LoginUser.java

public class LoginUser {
    private Integer userId;
    private String username;
    private String password;
    private String role;

    生成getter和setter......

}

JwtUser.java

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.Collections;

public class JwtUser implements UserDetails{
    private Integer id;
    private String username;
    private String password;
    private Collection<? extends GrantedAuthority> authorities;

    public JwtUser(){
    }

    public JwtUser(LoginUser loginUser){
        this.id = loginUser.getUserId();
        this.username = loginUser.getUsername();
        this.password = loginUser.getPassword();
        authorities = Collections.signleton(new SimpleGrantedAuthority(loginUser.getRole()));
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities(){
        return authorities;
    }

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

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

    //账号是否未过期
    @Override
    public boolean isAccountNonExpired(){
        return true;
    }

    //账号是否未锁定
    @Override
    public boolean isAccountNonLocked(){
        return true
    }

    //账号凭证是否未过期
    @Override
    public boolean isCredentialsNonExpired(){
        return true;
    }

    @Override
    public boolean isEnabled(){
        return true;
    }

    
}

2. Préparer JwtTokenUtils

import com.bean.JwtUser;
import io.jsonwebtoken.*;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JwtTokenUtils {
    
    public static final String TOKEN_HEADER = "Authorization";
    public static final String TOKEN_PREFIX = "Bearer ";
    public static final String SECRET = "jwtsecret";
    public static final String ISS = "echisan";

    private static final Long EXPIRATION = 60 * 60 * 3;//过期时间3小时
    private static final String ROLE = "role";

    //创建token
    public static String createToken(String username, String role, boolean isRememberMe){
        Map map = new HashMap();
        map.put(ROLE, role);
        return Jwts.builder()
                 .signWith(SignatureAlgorithm.HS512, SECRET)
                 .setClaims(map)
                 .setIssuer(ISS)
                 .setSubject(username)
                 .setIssuedAt(new Date())
                 .setExpiration(new Date(System.currentTimeMillis() + expiration * 1000))
                 .compact();
    }

    //从token中获取用户名(此处的token是指去掉前缀之后的)
    public static String getUserName(String token){
        String username;
        try {
            username = getTokenBody(token).getSubject();
        } catch (    Exception e){
            username = null;
        }
        return username;
    }

    public static String getUserRole(String token){
        return (String) getTokenBody(token).get(ROLE);
    }

    private static Claims getTokenBody(String token){
        Claims claims = null;
        try{
            claims = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token).getBody();
        } catch(ExpiredJwtException e){
            e.printStackTrace();
        } catch(UnsupportedJwtException e){
            e.printStackTrace();
        } catch(MalformedJwtException e){
            e.printStackTrace();
        } catch(SignatureException e){
            e.printStackTrace();
        } catch(IllegalArgumentException e){
            e.printStackTrace();
        }
    }

    //是否已过期
    public static boolean isExpiration(String token){
        try{
            return getTokenBody(token).getExpiration().before(new Date());
        } catch(Exception e){
            e.printStackTrace;
        }
        return true;
    }
}

3 . Préparez JWTAuthenticationFilter (vérifier la connexion), JWTAuthorizationFilter (identifier l'autorité) et la classe UserDetailsServiceImpl (vérifier la base de données pour correspondre au mot de passe du compte)

1.JWTAuthenticationFilter.java (vérifier la connexion)

public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilter{
    private AuthenticationManager authenticationManager;

    public JWTAuthenticationFilter(AuthenticationManager authenticationManager){
        this.authenticationManager = authenticationManager;
        setAuthenticationFailureHandler(new FailHandler());//设置账号密码错误时的处理方式
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException{
        //从输入流中获取登录的信息
        String username = request.getParameter("username");
        String password = request.getParameter("password");
        return authenticationManager.authenticate(
                       new UsernamePasswordAuthenticationToken(username, password, new ArrayList<>())
        );
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request,
                              HttpServletResponse response, FilterChain chain, Authentication authResult
) throws IOException, ServletException{
        JwtUser jwtUser = (JwtUser) authResult.getPrincipal();
        Collection<? extends GrantedAuthority> authorities = jwtUser.getAuthorities();
        String role = "";
        for(GrantedAuthority authority : authorities){
            role = authority.getAuthority();
        }
        String token = JwtTokenUtils.createToken(jwtUser.getUsername, role, false);
        //返回创建成功的token
        //但是这里创建的token只是单纯的token,按照jwt的规定,
        //最后请求的格式应该是 “Bearer token“。
        response.addHeader(JwtTokenUtils.TOKEN_HEADER, JwtTokenUtils.TOKEN_PREFIX + token);
    }

    //@Override
    //protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response,
    //                          AuthenticationException failed) throws IOException, ServletException {
    //    response.getWriter().write("authentication failed, reason: " + failed.getMessage());
    //}
}

2.JWTAuthorizationFilter.java (identifier l'autorité)

public class JWTAuthorizationFilter extends BasicAuthenticationFilter{

    public JWTAuthorizationFilter(AuthenticationManager authenticationManager){
        super(authenticationManager);
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
                              FilterChain chain) throws IOException, ServletException {
        String tokenHeader = request.getHeader(JwtTokenUtils.TOKEN_HEADER);
        //如果请求头中没有Authorization信息则直接放行了
        if(tokenHeader == null || !tokenHeader.startsWith(JwtTokenUtils.TOKEN_PREFIX)){
            chain.doFilter(request, response);
            return;
        }
        //如果请求头中有token,则进行解析,并且设置认证信息
        if(!JwtTokenUtils.isExpiration(tokenHeader.replace(JwtTokenUtils.TOKEN_PREFIX, “”))){
            SecurityContextHolder.getContext().setAuthentication(getAuthentication(tokenHeader));
        }
        chain.doFilter(request, response);
    }

    private UsernamePasswordAuthenticationToken getAuthentication(String tokenHeader){
        String token = tokenHeader.replace(JwtTokenUtils.TOKEN_PREFIX, “”);
        String username = JwtTokenUtils.getUserName(token);
        if(username != null){
            return new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>());
            
        }
        return null;
    }
}

. 3.UserDetailsServiceImpl.java (Vérifiez que la base de données correspond au mot de passe du compte)

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

@Service
public class UserDetailsServiceImpl implements UserDetailsService{

    @Autowired
    UserMapper userMapper;
    
    public BCryptPasswordEncoder bCryptPasswordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        LoginUser loginUser = usersMapper.selectByUserAccount(s);
        loginUser.setPassword(bCryptPasswordEncoder().encode(loginUser.getPassword()));
        return new JwtUser(loginUser);
    }
}

Four.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer