package com.gkhy.safePlatform.config.security; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.gkhy.safePlatform.account.rpc.apimodel.UserAccountService; import com.gkhy.safePlatform.commons.co.CacheAuthority; import com.gkhy.safePlatform.commons.co.CacheUser; import com.gkhy.safePlatform.commons.enums.RedisKeyEnum; import com.gkhy.safePlatform.commons.enums.ResultCodes; import com.gkhy.safePlatform.commons.exception.BusinessException; import com.gkhy.safePlatform.commons.utils.StringUtils; import com.gkhy.safePlatform.commons.vo.ResultVO; import org.apache.dubbo.config.annotation.DubboReference; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; 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; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; /** * @Description: token登录过滤器 */ @Component public class TokenAuthenticationFilter extends OncePerRequestFilter { @Autowired private TokenConfig tokenConfig; @DubboReference(check = false) private UserAccountService userAccountService; @Override protected void doFilterInternal(HttpServletRequest req, HttpServletResponse resp, FilterChain chain) throws IOException, ServletException { try { //获取当前认证成功用户权限信息 UsernamePasswordAuthenticationToken authRequest = getAuthentication(req, resp); if (authRequest != null) { SecurityContextHolder.getContext().setAuthentication(authRequest); } // 执行下一个 filter 过滤器链 chain.doFilter(req, resp); } catch (BusinessException e) { // 返回异常 this.writeJSON(req, resp, new ResultVO<>(e.getError())); } } private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest req,HttpServletResponse resp) { // header获取token String authToken = req.getHeader(tokenConfig.getHeader()); String loginUserId = req.getHeader(tokenConfig.getLoginUserHeader()); if(authToken != null) { // header 传入 userId if (StringUtils.isBlank(loginUserId)) { throw new BusinessException(ResultCodes.CLIENT_CREDENTIALS_LACK); } // 登录成功时,会将权限数据存入redis // 这里是验证获取权限信息 // 1.从redis中获取对应该用户的权限信息 String accessTokenKey = RedisKeyEnum.authKey(RedisKeyEnum.AUTH_TOKEN, loginUserId); String o = userAccountService.getValueByKeyFromRedis(accessTokenKey); // 2.token是否存在 if (o == null) { // 是否存在 throw new BusinessException(ResultCodes.CLIENT_CREDENTIALS_SIGN_INVALID); }else{ Long userId = Long.valueOf(loginUserId); CacheUser cacheUser = JSONObject.parseObject(o, CacheUser.class); assert userId.equals(cacheUser.getUserId()); if ( !authToken.equals(cacheUser.getAccessToken())) { throw new BusinessException(ResultCodes.CLIENT_CREDENTIALS_TOKEN_INVALID); } // 3.redis获取权限 String authoritiesKey = RedisKeyEnum.authKey(RedisKeyEnum.AUTH_AUTHORITIES, userId); String oo = userAccountService.getValueByKeyFromRedis(authoritiesKey); List authorities = new ArrayList<>(); // 4.redis中是否存在 if (oo != null) { // 5.存在 List cacheAuthorities = JSONArray.parseArray(oo, CacheAuthority.class); for (CacheAuthority cacheAuthority: cacheAuthorities) { authorities.add(new SimpleGrantedAuthority(cacheAuthority.getAuthority())); } }else { // 6.不存在=>数据库查询 String roleCode = userAccountService.getUserRoleCodeByUserId(userId); // role authorities.add(new SimpleGrantedAuthority("ROLE_" + roleCode)); // permission List permissions = userAccountService.getUserPermissionByUserId(userId); for (String permission : permissions) { SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(permission); authorities.add(simpleGrantedAuthority); } } // security对象中存入登陆者信息 return new UsernamePasswordAuthenticationToken(userId,authToken,authorities); } } return null; } protected void writeJSON(HttpServletRequest req, HttpServletResponse resp, ResultVO resultVO) throws IOException { // 设置编码格式 resp.setContentType("text/json;charset=utf-8"); // 处理跨域问题 resp.setHeader("Access-Control-Allow-Origin", "*"); resp.setHeader("Access-Control-Allow-Methods", "POST, GET"); //输出JSON PrintWriter out = resp.getWriter(); out.write(JSONObject.toJSONString(resultVO)); out.flush(); out.close(); } }