commit message

This commit is contained in:
Chopper
2021-05-13 10:41:46 +08:00
commit 3785bdb3bb
1424 changed files with 100110 additions and 0 deletions

View File

@@ -0,0 +1,136 @@
package cn.lili.security;
import cn.hutool.core.util.StrUtil;
import cn.lili.common.cache.Cache;
import cn.lili.common.cache.CachePrefix;
import cn.lili.common.security.AuthUser;
import cn.lili.common.security.enums.SecurityEnum;
import cn.lili.common.security.enums.UserEnums;
import cn.lili.common.token.SecretKeyUtil;
import cn.lili.common.utils.ResponseUtil;
import com.google.gson.Gson;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.authentication.AuthenticationManager;
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.security.web.authentication.www.BasicAuthenticationFilter;
import javax.naming.NoPermissionException;
import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author Chopper
*/
@Slf4j
public class ManagerAuthenticationFilter extends BasicAuthenticationFilter {
private final Cache cache;
public ManagerAuthenticationFilter(AuthenticationManager authenticationManager,
Cache cache) {
super(authenticationManager);
this.cache = cache;
}
@SneakyThrows
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) {
//从header中获取jwt
String jwt = request.getHeader(SecurityEnum.HEADER_TOKEN.getValue());
// 如果没有token 则return
if (StrUtil.isBlank(jwt)) {
chain.doFilter(request, response);
return;
}
//获取用户信息存入context
UsernamePasswordAuthenticationToken authentication = getAuthentication(jwt, response);
//自定义权限过滤
customAuthentication(request, response, authentication);
SecurityContextHolder.getContext().setAuthentication(authentication);
chain.doFilter(request, response);
}
/**
* 自定义权限过滤
*
* @param request
* @param authentication
*/
private void customAuthentication(HttpServletRequest request, HttpServletResponse response, UsernamePasswordAuthenticationToken authentication) throws NoPermissionException {
AuthUser authUser = (AuthUser) authentication.getDetails();
Map<String, List<String>> permission = (Map<String, List<String>>) cache.get(CachePrefix.PERMISSION_LIST.getPrefix(UserEnums.MANAGER) + authUser.getId());
if (authUser.getIsSuper()) {
return;
} else {
//用户是否拥有权限判定œ
//获取数据权限
// if (request.getMethod().equals(RequestMethod.GET.name())) {
// if (!PatternMatchUtils.simpleMatch(permission.get(PermissionEnum.SUPER).toArray(new String[0]), request.getRequestURI()) ||
// PatternMatchUtils.simpleMatch(permission.get(PermissionEnum.QUERY).toArray(new String[0]), request.getRequestURI())) {
//
// ResponseUtil.output(response, ResponseUtil.resultMap(false, 401, "抱歉,您没有访问权限"));
// throw new NoPermissionException("权限不足");
// }
// } else {
// if (!PatternMatchUtils.simpleMatch(permission.get(PermissionEnum.SUPER).toArray(new String[0]), request.getRequestURI())) {
//
// ResponseUtil.output(response, ResponseUtil.resultMap(false, 401, "抱歉,您没有访问权限"));
// throw new NoPermissionException("权限不足");
// }
// }
return;
}
}
/**
* 获取token信息
*
* @param jwt
* @param response
* @return
*/
private UsernamePasswordAuthenticationToken getAuthentication(String jwt, HttpServletResponse response) {
try {
Claims claims
= Jwts.parser()
.setSigningKey(SecretKeyUtil.generalKeyByDecoders())
.parseClaimsJws(jwt).getBody();
//获取存储在claims中的用户信息
String json = claims.get(SecurityEnum.USER_CONTEXT.getValue()).toString();
AuthUser authUser = new Gson().fromJson(json, AuthUser.class);
// 校验redis中是否有权限
if (cache.hasKey(CachePrefix.ACCESS_TOKEN.getPrefix(UserEnums.MANAGER) + jwt)) {
//用户角色
List<GrantedAuthority> auths = new ArrayList<>();
auths.add(new SimpleGrantedAuthority("ROLE_" + authUser.getRole().name()));
//构造返回信息
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(authUser.getUsername(), null, auths);
authentication.setDetails(authUser);
return authentication;
}
ResponseUtil.output(response, 403, ResponseUtil.resultMap(false, 403, "登录已失效,请重新登录"));
return null;
} catch (ExpiredJwtException e) {
log.debug("user analysis exception:", e);
} catch (Exception e) {
log.error("user analysis exception:", e);
}
return null;
}
}

View File

@@ -0,0 +1,80 @@
package cn.lili.security;
import cn.lili.common.cache.Cache;
import cn.lili.common.security.CustomAccessDeniedHandler;
import cn.lili.config.properties.IgnoredUrlsProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.web.cors.CorsConfigurationSource;
/**
* spring Security 核心配置类 Manager安全配置中心
*
* @author Chopper
* @date 2020/11/14 16:20
*/
@Slf4j
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ManagerSecurityConfig extends WebSecurityConfigurerAdapter {
/**
* 忽略验权配置
*/
private final IgnoredUrlsProperties ignoredUrlsProperties;
/**
* spring security -》 权限不足处理
*/
private final CustomAccessDeniedHandler accessDeniedHandler;
private final Cache<String> cache;
private final CorsConfigurationSource corsConfigurationSource;
@Override
protected void configure(HttpSecurity http) throws Exception {
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http
.authorizeRequests();
// 配置的url 不需要授权
for (String url : ignoredUrlsProperties.getUrls()) {
log.error(url);
registry.antMatchers(url).permitAll();
}
registry
.and()
// 禁止网页iframe
.headers().frameOptions().disable()
.and()
.authorizeRequests()
// 任何请求
.anyRequest()
// 需要身份认证
.authenticated()
.and()
// 允许跨域
.cors().configurationSource(corsConfigurationSource).and()
// 关闭跨站请求防护
.csrf().disable()
// 前后端分离采用JWT 不需要session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
// 自定义权限拒绝处理类
.exceptionHandling().accessDeniedHandler(accessDeniedHandler)
.and()
// 添加JWT认证过滤器
.addFilter(new ManagerAuthenticationFilter(authenticationManager(), cache));
}
}