TokenFilter -shiro

import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.web.filter.authc.AuthenticatingFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * 权限拦截器,校验每次请求是否有权限 token有没有过期
 */
@Slf4j
public class TokenFilter extends AuthenticatingFilter {
    @Value("${auth.white}")
    private String[] whiteList;
    @Value("${auth.open}")
    private Integer authOpen;

    @Autowired
    private UserService userService;
    @Autowired
    private LoginService loginService;
    @Autowired
    private AuthViewService authViewService;
    @Autowired
    private UserTokenService userTokenService;
    @Autowired
    private SysDictionaryService sysDictionaryService;
    @Autowired
    private UserChangePwdService userChangePwdService;
    @Autowired
    private ResourceI18nService resourceI18nService;


    /**
     * 创建Token, 支持自定义Token
     */
    @Override
    protected AuthenticationToken createToken(ServletRequest servletRequest, ServletResponse servletResponse) {
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        UserTokenCheckBO cookieUser = GetValueFromCookie.getInfoFromCookie(request.getCookies());
        return new UserToken(cookieUser.getUserId(), cookieUser.getToken(),
                cookieUser.getResTag(), cookieUser.getSystemId(),
                cookieUser.getSystemTag(), cookieUser.getUsername(), cookieUser.getStationCode());
    }

    @Override
    protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object mappedValue) {
        if (null == authOpen || authOpen == 0) {
            log.info("当前关闭校验");
            return true;
        }
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        String uri = request.getRequestURI();
        log.info("当前url是{}", uri);
        if (!checkUrl(uri)) {
            UserTokenCheckBO cookieUser = GetValueFromCookie.getInfoFromCookie(request.getCookies());
            Long systemId = null;
            if (StringUtils.isNotBlank(cookieUser.getSystemId()) &&
                    !cookieUser.getSystemId().equalsIgnoreCase("undefined")) {
                systemId = Long.valueOf(cookieUser.getSystemId());
            }
            List<AuthViewBO> authViewBOS = authViewService.getWhiteList(cookieUser.getSystemTag(), systemId);
            if (CollUtil.isNotEmpty(authViewBOS)) {
                for (AuthViewBO auth : authViewBOS) {
                    if (null != auth.getUrl() && uri.contains(auth.getUrl())) {
                        return true;
                    }
                    if (null != cookieUser && StringUtils.isNotBlank(cookieUser.getResTag())
                            && StringUtils.isNotBlank(auth.getResTag())
                            && cookieUser.getResTag().equals(auth.getResTag())) {
                        return true;
                    }
                }
            }
        } else {
            return true;
        }
        return false;
    }

    private boolean checkUrl(String requestUri) {
        requestUri = requestUri.replaceAll(DOUBLE_SLASH, SINGLE_SLASH);
        if (null != whiteList && whiteList.length > 0) {
            for (String white : whiteList) {
                if (requestUri.endsWith(white)) {
                    return true;
                }
            }
        }
        return requestUri.contains("/login") || requestUri.contains("/logout")
                || requestUri.contains("/swagger-ui") || requestUri.contains("/me/password")
                || requestUri.contains("/webjars/") || requestUri.contains("/api-docs/")
                || requestUri.contains("swagger-resources/") || requestUri.contains("/v2/")
                || requestUri.contains("/forward/message/");
    }

    @Override
    protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {
        if (null == authOpen || authOpen == 0) {
            log.info("当前关闭校验");
            return true;
        }
        HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
        httpResponse.setCharacterEncoding("UTF-8");

        UserTokenCheckBO cookieUser = GetValueFromCookie.getInfoFromCookie(request.getCookies());
        String ipAddress = IpAddressUtil.getIpAddress(request);
        String langStr = sysDictionaryService.getCurUseSystemLang(ipAddress);
        log.info("shiro校验:当前用户cookie中信息{}", cookieUser);
        if (StringUtils.isBlank(cookieUser.getUserId()) ||
                StringUtils.isBlank(cookieUser.getToken())) {
            Map<String, Object> result = new HashMap<>();
            result.put("returnCode", AuthErrorCodes.NOT_LOGIN.exception().getCode());
            result.put("returnUserMsg",
                    getMsg(AuthErrorCodes.NOT_LOGIN.exception().getMsg(), langStr));
            httpResponse.getWriter().print(JSON.toJSONString(result));
            log.info("shiro校验:当前用户未登录{}", cookieUser);
            return false;
        }

        UserTokenExtBO userTokenBO = userService.getUserWithTokenById(cookieUser.getUserId());
        userTokenBO.setUsername(
                (null != userTokenBO.getUsername() && userTokenBO.getUsername().contains(";"))
                        ? userTokenBO.getUsername().split(";")[0] : userTokenBO.getUsername());

        log.info("当前获取用户信息为{}", userTokenBO);
        if (null == userTokenBO || null == userTokenBO.getUserId()) {
            Map<String, Object> result = new HashMap<>();
            result.put("returnCode", AuthErrorCodes.USER_CLOSE_NULL.exception().getCode());
            result.put("returnUserMsg",
                    getMsg(AuthErrorCodes.USER_CLOSE_NULL.exception().getMsg(), langStr));
            httpResponse.getWriter().print(JSON.toJSONString(result));
            log.info("shiro校验:根据cookie的userId用户不存在或者已停用{}", userTokenBO);
            return false;
        }
        if (userTokenBO.isExpire()) {
            Map<String, Object> result = new HashMap<>();
            result.put("returnCode", AuthErrorCodes.USER_EXPIRED_ERROR.exception().getCode());
            result.put("returnUserMsg",
                    getMsg(AuthErrorCodes.USER_EXPIRED_ERROR.exception().getMsg(), langStr));
            httpResponse.getWriter().print(JSON.toJSONString(result));
            log.info("shiro校验:根据cookie的userId获取当前用户但是已经过期{}", userTokenBO);
            return false;
        }

        if (null == userTokenBO.getToken() || !userTokenBO.getToken().equals(cookieUser.getToken())) {
            Map<String, Object> result = new HashMap<>();
            result.put("returnCode", AuthErrorCodes.LOGIN_REPEAT.exception().getCode());
            result.put("returnUserMsg",
                    getMsg(AuthErrorCodes.LOGIN_REPEAT.exception().getMsg(), langStr));
            httpResponse.getWriter().print(JSON.toJSONString(result));
            log.info("shiro校验:根据cookie的userId获取当前用户TOKEN不一致{}", userTokenBO);
            return false;
        }
        Long userId = Long.valueOf(cookieUser.getUserId());

        if (userChangePwdService.isExpire(userId,userTokenBO.getClientId())) {
            loginService.logout(
                    UserWithTerminalReqBO.builder()
                            .userId(userId)
                            .username(userTokenBO.getUsername())
                            .systemId(cookieUser.getSystemId())
                            .terminal(cookieUser.getTerminal())
                            .build(),
                    "密码失效",
                    false);
            Map<String, Object> result = new HashMap<>();
            result.put("returnCode", AuthErrorCodes.USER_PWD_EXPIRE.exception().getCode());
            result.put("returnUserMsg",
                    getMsg(AuthErrorCodes.USER_PWD_EXPIRE.exception().getMsg(), langStr));
            httpResponse.getWriter().print(JSON.toJSONString(result));
            log.info("shiro校验:当前用户密码失效{}", userTokenBO);
            return false;
        }

        if (userTokenBO.getUsername().equals(SUPER_USER)) {
            log.info("当前超级用户不需要限制");
            userTokenService.updateTime(userId);
            return true;
        }

        if (StringUtils.isNotBlank(cookieUser.getResTag())) {
            if (!userService.hasTheRight(cookieUser.getSystemId(), Long.valueOf(cookieUser.getUserId()), cookieUser.getResTag())) {
                Map<String, Object> result = new HashMap<>();
                result.put("returnCode", AuthErrorCodes.NO_RIGHT.exception().getCode());
                result.put("returnUserMsg",
                        getMsg(AuthErrorCodes.NO_RIGHT.exception().getMsg(), langStr));
                httpResponse.getWriter().print(JSON.toJSONString(result));
                log.info("shiro校验:当前用户没有权限{}", cookieUser);
                return false;
            }
        }

        userTokenService.updateTime(userId);
        return true;
    }

    @Override
    protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest servletResponse, ServletResponse servletRequest) {
        HttpServletResponse httpResponse = (HttpServletResponse) servletResponse;
        httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
        httpResponse.setCharacterEncoding("UTF-8");
        HttpServletRequest request = (HttpServletRequest) servletRequest;
        try {
            Map<String, Object> result = new HashMap<>();
            result.put("returnCode", AuthErrorCodes.LOGIN_FAIL.exception().getCode());
            result.put("returnUserMsg",
                    getMsg(AuthErrorCodes.LOGIN_FAIL.exception().getMsg(),
                            sysDictionaryService.getCurUseSystemLang(IpAddressUtil.getIpAddress(request))));
            httpResponse.getWriter().print(JSON.toJSONString(result));
        } catch (IOException ioException) {
            log.info("shiro校验:当前shiro解析出现了问题{}", e, e);
        }
        return false;
    }

    private String getMsg(String message, String lang) {
        return resourceI18nService.getResNameByLange(lang, message);
    }

}

import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.crypto.hash.Sha512Hash;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.InvalidSessionException;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.SessionKey;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.Map;

@Configuration
@DependsOn({ "userService", "authViewService"})
public class AuthConfig {
    @Autowired
    private UserService userService;
    @Autowired
    private AuthViewService authViewService;

    @Value("${session.update:300000}")
    private Integer sessionUpdateTime;

    @Bean
    public TokenFilter tokenFilter(){
        return new TokenFilter();
    }

    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher() {
        HashedCredentialsMatcher hashMatcher = new HashedCredentialsMatcher();
        hashMatcher.setHashAlgorithmName(Sha512Hash.ALGORITHM_NAME);
        hashMatcher.setStoredCredentialsHexEncoded(false);
        hashMatcher.setHashIterations(1);
        return hashMatcher;
    }

    @Bean
    public Realm realm() {
        return new AuthRealm();
    }

    @Bean
    public ShiroService shiroService() {
        return new ShiroServiceImpl();
    }

    @Bean
    public DefaultWebSecurityManager securityManager(SessionManager sessionManager) {
        DefaultWebSecurityManager defaultSecurityManager = new DefaultWebSecurityManager();
        defaultSecurityManager.setRealm(realm());
        defaultSecurityManager.setSessionManager(sessionManager);
        return defaultSecurityManager;
    }

    @Bean
    public SessionManager sessionManager(AuthSessionDao sessionDao) {
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager() {
            @Override
            public void touch(SessionKey key) throws InvalidSessionException {
                Session session = doGetSession(key);
                if (session != null) {
                    long oldTime = session.getLastAccessTime().getTime();
                    session.touch(); // 更新访问时间
                    long newTime = session.getLastAccessTime().getTime();
                    if (newTime - oldTime >sessionUpdateTime ) { // 如果两次访问的时间间隔大于5分钟,主动持久化Session
                        onChange(session);
                    }
                }
            }
        };
        sessionManager.setSessionDAO(sessionDao);
        return sessionManager;
    }

    @Bean
    public ShiroFilterFactoryBean shiroFilterChainDefinition(DefaultWebSecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
        shiroFilterFactoryBean.setSecurityManager(securityManager);
        Map<String, Filter> filters = new HashMap<>(2);
        filters.put("tokenFilter", new TokenFilter());
        shiroFilterFactoryBean.setFilters(filters);
        shiroFilterFactoryBean.setFilterChainDefinitionMap(
                shiroService().loadFilterChainDefinitionMap());
        //authc表示需要验证身份才能访问,还有一些比如anon表示不需要验证身份就能访问等。
        shiroFilterFactoryBean.setLoginUrl("/login");
        return shiroFilterFactoryBean;
    }

}

@Slf4j
//@Component
public class AuthRealm extends AuthorizingRealm {
    @Lazy
    @Autowired
    private UserService userService;
    @Autowired
    private UserTokenService userTokenService;

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        return null;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        UserTokenExtBO userTokenExtBO = new UserTokenExtBO();
        if (authenticationToken instanceof UserToken) {

            log.info("当前是userToken");
            UserToken token = (UserToken) authenticationToken;

            if (null == token || StringUtils.isBlank(token.getUserId())) {
                throw new UnknownAccountException("No account found for admin ");
            }

            userTokenExtBO = userService.getUserWithTokenById(token.getUserId());
            if (userTokenExtBO == null) {
                throw new UnknownAccountException("No account found for admin [" + Long.valueOf(token.getUserId()) + "]");
            }

            return new SimpleAuthenticationInfo(userTokenExtBO, token.getToken(), getName());

        } else {

            AuthUserToken wesUserToken = (AuthUserToken) authenticationToken;
            if (wesUserToken.getUsername() == null) {
                throw new AccountException("Null usernames are not allowed by this realm.");
            }

            String[] username = wesUserToken.getUsername().split(";");
            userTokenExtBO = userService.getUserWithTokenByName(username[0], username.length > 1 ? username[1] : "");
            if (userTokenExtBO == null) {
                throw new UnknownAccountException("No account found for admin [" + username[0] + "]");
            }

            SimpleAuthenticationInfo authenticationInfo =
                    new SimpleAuthenticationInfo(userTokenExtBO, userTokenExtBO.getPassword(), getName());

            if (userTokenExtBO.getSalt() != null) {
                authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes(userTokenExtBO.getSalt()));
            }
            return authenticationInfo;
        }
    }

    @Override
    public boolean supports(AuthenticationToken token) {
        var superRs = super.supports(token);
        if (!superRs) {
            return token instanceof UserToken;
        }
        return true;
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值