zoukankan      html  css  js  c++  java
  • JwtUser JwtAuthenticationEntryPoint JwtAuthorizationTokenFilter JwtUserDetailsService AuthenticationController

    package me.zhengjie.core.security;
    
    import com.fasterxml.jackson.annotation.JsonIgnore;
    import lombok.AllArgsConstructor;
    import lombok.Getter;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.userdetails.UserDetails;
    
    import java.sql.Timestamp;
    import java.util.*;
    
    /**
     * @author jie
     * @date 2018-11-23
     */
    @Getter
    @AllArgsConstructor
    public class JwtUser implements UserDetails {
    
        @JsonIgnore
        private final Long id;
    
        private final String username;
    
        @JsonIgnore
        private final String password;
    
        private final String avatar;
    
        private final String email;
    
        @JsonIgnore
        private final Collection<? extends GrantedAuthority> authorities;
    
        private final boolean enabled;
    
        private Timestamp createTime;
    
        @JsonIgnore
        private final Date lastPasswordResetDate;
    
        @JsonIgnore
        @Override
        public boolean isAccountNonExpired() {
            return true;
        }
    
        @JsonIgnore
        @Override
        public boolean isAccountNonLocked() {
            return true;
        }
    
        @JsonIgnore
        @Override
        public boolean isCredentialsNonExpired() {
            return true;
        }
    
        @JsonIgnore
        @Override
        public String getPassword() {
            return password;
        }
    
        @Override
        public boolean isEnabled() {
            return enabled;
        }
    
        /**
         * 在我们保存权限的时候加上了前缀ROLE_,因此在这里需要处理下数据
         * @return
         */
        public Collection getRoles() {
            Set<String> roles = new LinkedHashSet<>();
            for (GrantedAuthority authority : authorities) {
                roles.add(authority.getAuthority().substring(5));
            }
            return roles;
        }
    }
    package me.zhengjie.core.security;
    
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.security.web.AuthenticationEntryPoint;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.Serializable;
    
    @Component
    public class
    JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable {
    
        private static final long serialVersionUID = -8970718410437077606L;
    
        @Override
        public void commence(HttpServletRequest request,
                             HttpServletResponse response,
                             AuthenticationException authException) throws IOException {
            /**
             * 当用户尝试访问安全的REST资源而不提供任何凭据时,将调用此方法发送401 响应
             */
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException==null?"Unauthorized":authException.getMessage());
        }
    }
    package me.zhengjie.core.security;
    
    import org.springframework.security.core.AuthenticationException;
    import org.springframework.security.web.AuthenticationEntryPoint;
    import org.springframework.stereotype.Component;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.Serializable;
    
    @Component
    public class
    JwtAuthenticationEntryPoint implements AuthenticationEntryPoint, Serializable {
    
        private static final long serialVersionUID = -8970718410437077606L;
    
        @Override
        public void commence(HttpServletRequest request,
                             HttpServletResponse response,
                             AuthenticationException authException) throws IOException {
            /**
             * 当用户尝试访问安全的REST资源而不提供任何凭据时,将调用此方法发送401 响应
             */
            response.sendError(HttpServletResponse.SC_UNAUTHORIZED, authException==null?"Unauthorized":authException.getMessage());
        }
    }
    package me.zhengjie.core.security;
    
    import io.jsonwebtoken.ExpiredJwtException;
    import me.zhengjie.core.utils.JwtTokenUtil;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Qualifier;
    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.stereotype.Component;
    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;
    
    @Component
    public class JwtAuthorizationTokenFilter extends OncePerRequestFilter {
    
        private final Logger logger = LoggerFactory.getLogger(this.getClass());
    
        private final UserDetailsService userDetailsService;
        private final JwtTokenUtil jwtTokenUtil;
        private final String tokenHeader;
    
        public JwtAuthorizationTokenFilter(@Qualifier("jwtUserDetailsService") UserDetailsService userDetailsService, JwtTokenUtil jwtTokenUtil, @Value("${jwt.header}") String tokenHeader) {
            this.userDetailsService = userDetailsService;
            this.jwtTokenUtil = jwtTokenUtil;
            this.tokenHeader = tokenHeader;
        }
    
        @Override
        protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
            logger.debug("processing authentication for '{}'", request.getRequestURL());
    
            final String requestHeader = request.getHeader(this.tokenHeader);
    
            String username = null;
            String authToken = null;
            if (requestHeader != null && requestHeader.startsWith("Bearer ")) {
                authToken = requestHeader.substring(7);
                try {
                    username = jwtTokenUtil.getUsernameFromToken(authToken);
                } catch (ExpiredJwtException e) {
                   logger.error(e.getMessage());
                }
            }
    
            logger.debug("checking authentication for user '{}'", username);
    
            if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                logger.debug("security context was null, so authorizating user");
    
                // It is not compelling necessary to load the use details from the database. You could also store the information
                // in the token and read it from it. It's up to you ;)
                UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
    
                // For simple validation it is completely sufficient to just check the token integrity. You don't have to call
                // the database compellingly. Again it's up to you ;)
                if (jwtTokenUtil.validateToken(authToken, userDetails)) {
                    UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
                    authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                    logger.info("authorizated user '{}', setting security context", username);
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }
            }
            chain.doFilter(request, response);
        }
    }
    package me.zhengjie.core.service;
    
    import me.zhengjie.common.exception.EntityNotFoundException;
    import me.zhengjie.common.utils.ValidationUtil;
    import me.zhengjie.core.security.JwtUser;
    import me.zhengjie.system.domain.Permission;
    import me.zhengjie.system.domain.Role;
    import me.zhengjie.system.domain.User;
    import me.zhengjie.system.repository.PermissionRepository;
    import me.zhengjie.system.repository.UserRepository;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.cache.annotation.CacheConfig;
    import org.springframework.cache.annotation.Cacheable;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.authority.SimpleGrantedAuthority;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    import java.util.ArrayList;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    import java.util.stream.Collectors;
    
    /**
     * @author jie
     * @date 2018-11-22
     */
    @Service
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
    public class JwtUserDetailsService implements UserDetailsService {
    
        @Autowired
        private UserRepository userRepository;
    
        @Autowired
        private PermissionRepository permissionRepository;
    
        @Override
        public UserDetails loadUserByUsername(String username){
    
            User user = null;
            if(ValidationUtil.isEmail(username)){
                user = userRepository.findByEmail(username);
            } else {
                user = userRepository.findByUsername(username);
            }
    
            if (user == null) {
                throw new EntityNotFoundException(User.class, "name", username);
            } else {
                return create(user);
            }
        }
    
        public UserDetails create(User user) {
            return new JwtUser(
                    user.getId(),
                    user.getUsername(),
                    user.getPassword(),
                    user.getAvatar(),
                    user.getEmail(),
                    mapToGrantedAuthorities(user.getRoles(),permissionRepository),
                    user.getEnabled(),
                    user.getCreateTime(),
                    user.getLastPasswordResetTime()
            );
        }
    
        private static List<GrantedAuthority> mapToGrantedAuthorities(Set<Role> roles,PermissionRepository permissionRepository) {
    
            Set<Permission> permissions = new HashSet<>();
            for (Role role : roles) {
                Set<Role> roleSet = new HashSet<>();
                roleSet.add(role);
                permissions.addAll(permissionRepository.findByRoles(roleSet));
            }
    
            return permissions.stream()
                    .map(permission -> new SimpleGrantedAuthority("ROLE_"+permission.getName()))
                    .collect(Collectors.toList());
        }
    }
    package me.zhengjie.core.service;
    
    import me.zhengjie.common.exception.EntityNotFoundException;
    import me.zhengjie.common.utils.ValidationUtil;
    import me.zhengjie.core.security.JwtUser;
    import me.zhengjie.system.domain.Permission;
    import me.zhengjie.system.domain.Role;
    import me.zhengjie.system.domain.User;
    import me.zhengjie.system.repository.PermissionRepository;
    import me.zhengjie.system.repository.UserRepository;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.cache.annotation.CacheConfig;
    import org.springframework.cache.annotation.Cacheable;
    import org.springframework.security.core.GrantedAuthority;
    import org.springframework.security.core.authority.SimpleGrantedAuthority;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;
    import java.util.ArrayList;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    import java.util.stream.Collectors;
    
    /**
     * @author jie
     * @date 2018-11-22
     */
    @Service
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
    public class JwtUserDetailsService implements UserDetailsService {
    
        @Autowired
        private UserRepository userRepository;
    
        @Autowired
        private PermissionRepository permissionRepository;
    
        @Override
        public UserDetails loadUserByUsername(String username){
    
            User user = null;
            if(ValidationUtil.isEmail(username)){
                user = userRepository.findByEmail(username);
            } else {
                user = userRepository.findByUsername(username);
            }
    
            if (user == null) {
                throw new EntityNotFoundException(User.class, "name", username);
            } else {
                return create(user);
            }
        }
    
        public UserDetails create(User user) {
            return new JwtUser(
                    user.getId(),
                    user.getUsername(),
                    user.getPassword(),
                    user.getAvatar(),
                    user.getEmail(),
                    mapToGrantedAuthorities(user.getRoles(),permissionRepository),
                    user.getEnabled(),
                    user.getCreateTime(),
                    user.getLastPasswordResetTime()
            );
        }
    
        private static List<GrantedAuthority> mapToGrantedAuthorities(Set<Role> roles,PermissionRepository permissionRepository) {
    
            Set<Permission> permissions = new HashSet<>();
            for (Role role : roles) {
                Set<Role> roleSet = new HashSet<>();
                roleSet.add(role);
                permissions.addAll(permissionRepository.findByRoles(roleSet));
            }
    
            return permissions.stream()
                    .map(permission -> new SimpleGrantedAuthority("ROLE_"+permission.getName()))
                    .collect(Collectors.toList());
        }
    }
    package me.zhengjie.core.rest;
    
    import lombok.extern.slf4j.Slf4j;
    import me.zhengjie.common.aop.log.Log;
    import me.zhengjie.core.security.AuthenticationToken;
    import me.zhengjie.core.security.AuthorizationUser;
    import me.zhengjie.core.utils.JwtTokenUtil;
    import me.zhengjie.core.security.JwtUser;
    import me.zhengjie.core.utils.EncryptUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.http.ResponseEntity;
    import org.springframework.security.authentication.AccountExpiredException;
    import org.springframework.security.authentication.AuthenticationManager;
    import org.springframework.security.core.userdetails.UserDetails;
    import org.springframework.security.core.userdetails.UserDetailsService;
    import org.springframework.web.bind.annotation.*;
    import javax.servlet.http.HttpServletRequest;
    
    /**
     * @author jie
     * @date 2018-11-23
     * 授权、根据token获取用户详细信息
     */
    @Slf4j
    @RestController
    @RequestMapping("auth")
    public class AuthenticationController {
    
        @Value("${jwt.header}")
        private String tokenHeader;
    
        @Autowired
        private AuthenticationManager authenticationManager;
    
        @Autowired
        private JwtTokenUtil jwtTokenUtil;
    
        @Autowired
        @Qualifier("jwtUserDetailsService")
        private UserDetailsService userDetailsService;
    
        /**
         * 登录授权
         * @param authorizationUser
         * @return
         */
        @Log(description = "用户登录")
        @PostMapping(value = "${jwt.auth.path}")
        public ResponseEntity<?> authenticationLogin(@RequestBody AuthorizationUser authorizationUser){
    
            final UserDetails userDetails = userDetailsService.loadUserByUsername(authorizationUser.getUsername());
    
            if(!userDetails.getPassword().equals(EncryptUtils.encryptPassword(authorizationUser.getPassword()))){
                throw new AccountExpiredException("密码错误");
            }
    
            if(!userDetails.isEnabled()){
                throw new AccountExpiredException("账号已停用,请联系管理员");
            }
    
            // 生成令牌
            final String token = jwtTokenUtil.generateToken(userDetails);
    
            // 返回 token
            return ResponseEntity.ok(new AuthenticationToken(token));
        }
    
        /**
         * 获取用户信息
         * @param request
         * @return
         */
        @GetMapping(value = "${jwt.auth.account}")
        public ResponseEntity getUserInfo(HttpServletRequest request){
            JwtUser jwtUser = (JwtUser)userDetailsService.loadUserByUsername(jwtTokenUtil.getUserName(request));
            return ResponseEntity.ok(jwtUser);
        }
    }
    package me.zhengjie.core.security;
    
    import lombok.AllArgsConstructor;
    import lombok.Getter;
    import java.io.Serializable;
    
    /**
     * @author jie
     * @date 2018-11-23
     * 返回token
     */
    @Getter
    @AllArgsConstructor
    public class AuthenticationToken implements Serializable {
    
        private final String token;
    }
    package me.zhengjie.core.security;
    
    import lombok.Getter;
    import lombok.Setter;
    
    import javax.validation.constraints.NotBlank;
    
    /**
     * @author jie
     * @date 2018-11-30
     */
    @Getter
    @Setter
    public class AuthorizationUser {
    
        @NotBlank
        private String username;
    
        @NotBlank
        private String password;
    
        @Override
        public String toString() {
            return "{username=" + username  + ", password= ******}";
        }
    }
  • 相关阅读:
    codevs2606 约数和问题
    UOJ150 运输计划
    codevs1279 Guard 的无聊
    codevs1997 守卫者的挑战
    codevs1291 火车线路
    codevs1217 借教室
    codevs1281 Xn数列
    codevs1218 疫情控制
    codevs1199 开车旅行
    BZOJ1941 [Sdoi2010]Hide and Seek
  • 原文地址:https://www.cnblogs.com/tonggc1668/p/11216923.html
Copyright © 2011-2022 走看看