springSecurity-oauth2默认用户身份验证转换器( 方法上的注解权限authorities)

springSecurity-oauth2默认用户身份验证转换器

package com.xy.tasty.mgr.security;

import com.xy.common.verify.Asserts;
import com.xy.tasty.core.cache.UserContextCache;
import com.xy.tasty.core.exception.UnBindOrganizationException;
import com.xy.tasty.core.exception.UnAuthenticationException;
import com.xy.tasty.core.exception.UnBindAuthorityException;
import com.xy.tasty.core.security.AuthUserContext;
import com.xy.tasty.core.security.UserContext;
import com.xy.tasty.core.service.UserInfoService;
import com.xy.tasty.dao.core.dict.RoleEnum;
import com.xy.tasty.dao.core.entity.UserInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.oauth2.common.exceptions.InvalidTokenException;
import org.springframework.security.oauth2.provider.token.DefaultUserAuthenticationConverter;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.Map;
import java.util.Optional;

/**
 * @author Canaan
 * @date 2019/4/2 19:34
 */
@Component
public class CustomUserAuthenticationConverter extends DefaultUserAuthenticationConverter implements ApplicationContextAware {
    private final static Logger LOGGER = LoggerFactory.getLogger(CustomUserAuthenticationConverter.class);

    @Autowired
    private UserContextCache   userContextCache;
    @Autowired
    private UserInfoService    userInfoService;
    @Autowired
    private ApplicationContext applicationContext;


    @Override
    public Authentication extractAuthentication(Map<String, ?> map) {
        if (!map.containsKey(USERNAME) || map.get("id") == null) {
            //不是密码账号验证
            return null;
        }

        long beingTime = System.currentTimeMillis();

        try {
            String tokenName = "jti";
            if (map.get(tokenName) == null) {
                throw new InvalidTokenException("无效用户");
            }
            String token = map.get(tokenName).toString();

            UserInfo userInfo;
            Optional<UserInfo> userInfoOptional = this.userContextCache.getUser(token);
            if (userInfoOptional.isPresent()) {
                userInfo = userInfoOptional.get();
            } else {
                //验证用户的有效性
                userInfo = this.getUserAndVerify(map);
                if (userInfo == null) {
                    throw new InvalidTokenException("无效用户");
                }
                this.userContextCache.putUser(token, userInfo);
            }

            UserContext userContext = this.applicationContext.getBean(AuthUserContext.class, userInfo);
            Collection<? extends GrantedAuthority> authorities = userContext.getAuthorities();
            return new UsernamePasswordAuthenticationToken(userContext, "N/A", authorities);
        } finally {
            LOGGER.debug("------ userContext 解析时间:{} ms -------", System.currentTimeMillis() - beingTime);
        }
    }


    /**
     * 
  • 获取当前用户是到【用户中心】授权了.主要通过【用户中心】的用户id到数据库中查询
  • *
  • 如果用户来源是【食安】那么必须验证账号相同
  • *
  • 验证用户是否有资源操作【食安】,即产品权限
  • *
  • 验证【用户中心】的外部用户id,与【食安】一致
  • *
  • 【食安超级管理员】只能通过tastymgr / uums 端点授权
  • *
  • 验证用户是否已经分配了具体的角色
  • *
  • 验证用户是否被禁用了
  • * * @author Canaan * @date 2019/4/3 14:48 */
    private UserInfo getUserAndVerify(Map<String, ?> map) { Asserts.state("uums".equalsIgnoreCase(map.get("sub").toString())); //只能是通过用户中心发放令牌 String userName = map.get("user_name").toString(); try { UserInfo userInfo = this.userInfoService.getByOutId(Long.valueOf(map.get("id").toString())).orElse(null); if (userInfo == null) { throw new InvalidTokenException("非法用户请至【用户中心】授权"); } //TODO 如果用户来源是食安,那么账号要保持一致 //TODO 根据食安用户id和产品代码。查询线上是否已经授权了产品 //TODO 验证 用户id与食安用户一致 //TODO 验证用户是否已经分配了具体的角色 2019/7/24 11:02 //如果是管理员,那么客户端授权id只能是 tastymgr / uums if (userInfo.getRole() == RoleEnum.ADMIN) { switch (map.get("client_id").toString()) { case "tastymgr": case "uums": break; default: throw new InvalidTokenException("超管只能通过【tastymgr】端点来授权"); } } return userInfo; } catch (UnAuthenticationException e) { throw e; } catch (UnBindOrganizationException | UnBindAuthorityException e) { return null; } catch (Exception e) { LOGGER.error(e.getMessage(), e); return null; } } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } }
    package com.xy.tasty.core.security;
    
    import com.xy.common.verify.Asserts;
    import com.xy.tasty.core.exception.UnBindOrganizationException;
    import com.xy.tasty.core.service.BrandService;
    import com.xy.tasty.core.service.StoreService;
    import com.xy.tasty.dao.core.dict.RoleEnum;
    import com.xy.tasty.dao.core.dict.UserStatusEnum;
    import com.xy.tasty.dao.core.entity.Brand;
    import com.xy.tasty.dao.core.entity.Store;
    import com.xy.tasty.dao.core.entity.UserInfo;
    import org.apache.commons.lang3.builder.ToStringBuilder;
    import org.apache.commons.lang3.builder.ToStringStyle;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.config.ConfigurableBeanFactory;
    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Component;
    
    import java.util.Collection;
    import java.util.Collections;
    import java.util.HashSet;
    
    /**
     * @author Canaan
     * @date 2019/6/19 16:48
     */
    @Component
    @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public class AuthUserContext implements UserContext {
    
        private Long                                    id;                      //主键
        private RoleEnum                                role;                    //用户角色
        private String                                  username;                //登录账号
        private Collection<UserContextGrantedAuthority> authorities;             //权限集
        private String                                  nickname;                //用户呢称
        private String                                  password;                //登录密码
        private boolean                                 accountNonExpired;        //账号没有过期
        private boolean                                 accountNonLocked;         // 账号没有被锁定
        private boolean                                 credentialsNonExpired;    //证书没有过期
        private boolean                                 enabled;                  //是否可用
        private Long                                    pointId;                  //指向id
        @Autowired(required = false)
        private BrandService                            brandService;
        @Autowired(required = false)
        private StoreService                            storeService;
    
        public AuthUserContext() {
            this.authorities = new HashSet<>();
        }
    
        public AuthUserContext(UserInfo userInfo) {
            Asserts.notNull(userInfo);
            this.id = userInfo.getId();
            this.role = userInfo.getRole();
            this.username = userInfo.getUsername();
            UserContextGrantedAuthority authority = new UserContextGrantedAuthority("ROLE_" + userInfo.getRole());
            this.authorities = Collections.singletonList(authority);
            this.nickname = userInfo.getNickname();
            this.password = null;
            this.accountNonExpired = true;
            this.accountNonLocked = true;
            this.credentialsNonExpired = true;
            this.enabled = userInfo.getStatus() == UserStatusEnum.ENABLED;
            this.pointId = userInfo.getPointId();
        }
    
        /**
         * 获取【门店用户】所持有的门店
         *
         * @return
         */
        @Override
        public Store getStore() {
            if (getRole() != RoleEnum.STORE) {
                throw new IllegalStateException("仅限于门店用户调用");
            }
    
            Asserts.notNull(this.storeService);
            return this.storeService.getById(pointId).orElseThrow(UnBindOrganizationException::new);
        }
    
        /**
         * 获取【品牌用户】所持有的品牌
         *
         * @return
         */
        @Override
        public Brand getBrand() {
            if (getRole() != RoleEnum.BRAND) {
                throw new IllegalStateException("仅限于品牌用户调用");
            }
    
            Asserts.notNull(this.brandService);
            return this.brandService.getById(pointId).orElseThrow(UnBindOrganizationException::new);
        }
    
    
        public Long getPointId() {
            return pointId;
        }
    
        public void setPointId(Long pointId) {
            this.pointId = pointId;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public void setRole(RoleEnum role) {
            this.role = role;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        @Override
        public String getPassword() {
            return this.password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        @Override
        public Long getId() {
            return id;
        }
    
        @Override
        public RoleEnum getRole() {
            return role;
        }
    
        @Override
        public String getNickname() {
            return nickname;
        }
    
        @Override
        public String getUsername() {
            return username;
        }
    
        public boolean isAccountNonExpired() {
            return accountNonExpired;
        }
    
        public boolean isAccountNonLocked() {
            return accountNonLocked;
        }
    
        public boolean isCredentialsNonExpired() {
            return credentialsNonExpired;
        }
    
        public boolean isEnabled() {
            return enabled;
        }
    
        @Override
        public Collection<UserContextGrantedAuthority> getAuthorities() {
            return authorities;
        }
    
        public void setNickname(String nickname) {
            this.nickname = nickname;
        }
    
        public void setAccountNonLocked(Boolean accountNonLocked) {
            if (accountNonLocked == null) {
                return;
            }
            this.accountNonLocked = accountNonLocked;
        }
    
        public void setAccountNonExpired(Boolean accountNonExpired) {
            if (accountNonExpired == null) {
                return;
            }
            this.accountNonExpired = accountNonExpired;
        }
    
        public void setCredentialsNonExpired(Boolean credentialsNonExpired) {
            if (credentialsNonExpired == null) {
                return;
            }
            this.credentialsNonExpired = credentialsNonExpired;
        }
    
        public void setAuthorities(Collection<UserContextGrantedAuthority> authorities) {
            this.authorities.clear();
            this.authorities.addAll(authorities);
        }
    
        public void setEnabled(Boolean enabled) {
            if (enabled == null) {
                return;
            }
            this.enabled = enabled;
        }
    
        @Override
        public String toString() {
            return ToStringBuilder.reflectionToString(this, ToStringStyle.JSON_STYLE);
        }
    
    }
    
    

    你可能感兴趣的:(Spring,oauth2)