mirror of https://github.com/elunez/eladmin
				
				
				
			自定义权限校验,增加匿名访问注解,扩展PreAuthorize 匿名注解
							parent
							
								
									c9c86f046a
								
							
						
					
					
						commit
						938ae1fcd8
					
				|  | @ -0,0 +1,16 @@ | |||
| package me.zhengjie.annotation; | ||||
| 
 | ||||
| import java.lang.annotation.ElementType; | ||||
| import java.lang.annotation.Retention; | ||||
| import java.lang.annotation.RetentionPolicy; | ||||
| import java.lang.annotation.Target; | ||||
| 
 | ||||
| /** | ||||
|  * @author jacky | ||||
|  *  用于标记匿名访问方法 | ||||
|  */ | ||||
| @Target(ElementType.METHOD) | ||||
| @Retention(RetentionPolicy.RUNTIME) | ||||
| public @interface AnonymousAccess { | ||||
| 
 | ||||
| } | ||||
|  | @ -1,6 +1,7 @@ | |||
| package me.zhengjie.config; | ||||
| 
 | ||||
| import me.zhengjie.utils.SecurityUtils; | ||||
| import org.springframework.beans.factory.annotation.Value; | ||||
| import org.springframework.security.core.GrantedAuthority; | ||||
| import org.springframework.stereotype.Service; | ||||
| import java.util.Arrays; | ||||
|  | @ -11,6 +12,11 @@ import java.util.stream.Collectors; | |||
| public class ElPermissionConfig { | ||||
| 
 | ||||
|     public Boolean check(String ...permissions){ | ||||
|         // 如果是匿名访问的,就放行
 | ||||
|         String anonymous = "anonymous"; | ||||
|         if(Arrays.asList(permissions).contains(anonymous)){ | ||||
|             return true; | ||||
|         } | ||||
|         List<String> elPermissions = SecurityUtils.getUserDetails().getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toList()); | ||||
|         List<String> list = Arrays.stream(permissions).filter(elPermissions::contains).map(s -> s).collect(Collectors.toList()); | ||||
|         if(elPermissions.contains("admin") || list.size() != 0){ | ||||
|  |  | |||
|  | @ -2,7 +2,9 @@ package me.zhengjie.modules.monitor.rest; | |||
| 
 | ||||
| import io.swagger.annotations.Api; | ||||
| import io.swagger.annotations.ApiOperation; | ||||
| import me.zhengjie.annotation.AnonymousAccess; | ||||
| import me.zhengjie.annotation.Limit; | ||||
| import org.springframework.security.access.prepost.PreAuthorize; | ||||
| import org.springframework.web.bind.annotation.GetMapping; | ||||
| import org.springframework.web.bind.annotation.RequestMapping; | ||||
| import org.springframework.web.bind.annotation.RestController; | ||||
|  | @ -17,12 +19,14 @@ import java.util.concurrent.atomic.AtomicInteger; | |||
| @RequestMapping("/api/limit") | ||||
| @Api(tags = "系统:限流测试管理") | ||||
| public class LimitController { | ||||
| 
 | ||||
|     private static final AtomicInteger ATOMIC_INTEGER = new AtomicInteger(); | ||||
| 
 | ||||
|     /** | ||||
|      * 测试限流注解,下面配置说明该接口 60秒内最多只能访问 10次,保存到redis的键名为 limit_test, | ||||
|      */ | ||||
|     @GetMapping | ||||
|     @PreAuthorize("@el.check('anonymous')") | ||||
|     @ApiOperation("测试") | ||||
|     @Limit(key = "test", period = 60, count = 10, name = "testLimit", prefix = "limit") | ||||
|     public int testLimit() { | ||||
|  |  | |||
|  | @ -1,13 +1,17 @@ | |||
| package me.zhengjie.modules.security.config; | ||||
| 
 | ||||
| import me.zhengjie.annotation.AnonymousAccess; | ||||
| import me.zhengjie.config.ElPermissionConfig; | ||||
| import me.zhengjie.modules.security.security.JwtAuthenticationEntryPoint; | ||||
| import me.zhengjie.modules.security.security.JwtAuthorizationTokenFilter; | ||||
| import me.zhengjie.modules.security.service.JwtUserDetailsService; | ||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||
| import org.springframework.beans.factory.annotation.Value; | ||||
| import org.springframework.context.ApplicationContext; | ||||
| import org.springframework.context.annotation.Bean; | ||||
| import org.springframework.context.annotation.Configuration; | ||||
| import org.springframework.http.HttpMethod; | ||||
| import org.springframework.security.access.prepost.PreAuthorize; | ||||
| import org.springframework.security.authentication.AuthenticationManager; | ||||
| import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; | ||||
| import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; | ||||
|  | @ -19,6 +23,13 @@ import org.springframework.security.config.http.SessionCreationPolicy; | |||
| import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | ||||
| import org.springframework.security.crypto.password.PasswordEncoder; | ||||
| import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; | ||||
| import org.springframework.web.method.HandlerMethod; | ||||
| import org.springframework.web.servlet.mvc.method.RequestMappingInfo; | ||||
| import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; | ||||
| 
 | ||||
| import java.util.HashSet; | ||||
| import java.util.Map; | ||||
| import java.util.Set; | ||||
| 
 | ||||
| @Configuration | ||||
| @EnableWebSecurity | ||||
|  | @ -29,16 +40,19 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { | |||
| 
 | ||||
|     private final JwtUserDetailsService jwtUserDetailsService; | ||||
| 
 | ||||
|     private final ApplicationContext applicationContext; | ||||
| 
 | ||||
|     // 自定义基于JWT的安全过滤器
 | ||||
|     private final JwtAuthorizationTokenFilter authenticationTokenFilter; | ||||
| 
 | ||||
|     @Value("${jwt.header}") | ||||
|     private String tokenHeader; | ||||
| 
 | ||||
|     public SecurityConfig(JwtAuthenticationEntryPoint unauthorizedHandler, JwtUserDetailsService jwtUserDetailsService, JwtAuthorizationTokenFilter authenticationTokenFilter) { | ||||
|     public SecurityConfig(JwtAuthenticationEntryPoint unauthorizedHandler, JwtUserDetailsService jwtUserDetailsService, JwtAuthorizationTokenFilter authenticationTokenFilter, ApplicationContext applicationContext) { | ||||
|         this.unauthorizedHandler = unauthorizedHandler; | ||||
|         this.jwtUserDetailsService = jwtUserDetailsService; | ||||
|         this.authenticationTokenFilter = authenticationTokenFilter; | ||||
|         this.applicationContext = applicationContext; | ||||
|     } | ||||
| 
 | ||||
|     @Autowired | ||||
|  | @ -67,18 +81,26 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { | |||
| 
 | ||||
|     @Override | ||||
|     protected void configure(HttpSecurity httpSecurity) throws Exception { | ||||
| 
 | ||||
|         // 搜寻 匿名标记 url: PreAuthorize("hasAnyRole('anonymous')") 和 PreAuthorize("@el.check('anonymous')") 和 AnonymousAccess
 | ||||
|         Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = applicationContext.getBean(RequestMappingHandlerMapping.class).getHandlerMethods(); | ||||
|         Set<String> anonymousUrls = new HashSet<>(); | ||||
|         for (Map.Entry<RequestMappingInfo, HandlerMethod> infoEntry : handlerMethodMap.entrySet()) { | ||||
|             HandlerMethod handlerMethod = infoEntry.getValue(); | ||||
|             AnonymousAccess anonymousAccess = handlerMethod.getMethodAnnotation(AnonymousAccess.class); | ||||
|             PreAuthorize preAuthorize = handlerMethod.getMethodAnnotation(PreAuthorize.class); | ||||
|             if (null != preAuthorize && preAuthorize.value().contains("anonymous")) { | ||||
|                 anonymousUrls.addAll(infoEntry.getKey().getPatternsCondition().getPatterns()); | ||||
|             } else if (null != anonymousAccess && null == preAuthorize) { | ||||
|                 anonymousUrls.addAll(infoEntry.getKey().getPatternsCondition().getPatterns()); | ||||
|             } | ||||
|         } | ||||
|         httpSecurity | ||||
| 
 | ||||
|                 // 禁用 CSRF
 | ||||
|                 .csrf().disable() | ||||
| 
 | ||||
|                 // 授权异常
 | ||||
|                 .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and() | ||||
| 
 | ||||
|                 // 不创建会话
 | ||||
|                 .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() | ||||
| 
 | ||||
|                 // 过滤请求
 | ||||
|                 .authorizeRequests() | ||||
|                 .antMatchers( | ||||
|  | @ -88,31 +110,20 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { | |||
|                         "/**/*.css", | ||||
|                         "/**/*.js" | ||||
|                 ).anonymous() | ||||
| 
 | ||||
|                 .antMatchers(HttpMethod.POST,"/auth/login").permitAll() | ||||
|                 .antMatchers(HttpMethod.DELETE,"/auth/logout").permitAll() | ||||
|                 .antMatchers(HttpMethod.GET,"/auth/code").permitAll() | ||||
|                 // 支付宝回调
 | ||||
|                 .antMatchers("/api/aliPay/return").permitAll() | ||||
|                 .antMatchers("/api/aliPay/notify").permitAll() | ||||
| 
 | ||||
|                 // swagger start
 | ||||
|                 .antMatchers("/swagger-ui.html").permitAll() | ||||
|                 .antMatchers("/swagger-resources/**").permitAll() | ||||
|                 .antMatchers("/webjars/**").permitAll() | ||||
|                 .antMatchers("/*/api-docs").permitAll() | ||||
|                 // swagger end
 | ||||
| 
 | ||||
|                 // 接口限流测试
 | ||||
|                 .antMatchers("/test/**").permitAll() | ||||
|                 // 文件
 | ||||
|                 .antMatchers("/avatar/**").permitAll() | ||||
|                 .antMatchers("/file/**").permitAll() | ||||
| 
 | ||||
|                 // 放行OPTIONS请求
 | ||||
|                 .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() | ||||
| 
 | ||||
|                 .antMatchers("/druid/**").permitAll() | ||||
|                 // 自定义匿名访问所有url放行 : 允许 匿名和带权限以及登录用户访问
 | ||||
|                 .antMatchers(anonymousUrls.toArray(new String[0])).permitAll() | ||||
|                 // 所有请求都需要认证
 | ||||
|                 .anyRequest().authenticated() | ||||
|                 // 防止iframe 造成跨域
 | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ import com.wf.captcha.ArithmeticCaptcha; | |||
| import io.swagger.annotations.Api; | ||||
| import io.swagger.annotations.ApiOperation; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import me.zhengjie.annotation.AnonymousAccess; | ||||
| import me.zhengjie.aop.log.Log; | ||||
| import me.zhengjie.exception.BadRequestException; | ||||
| import me.zhengjie.modules.monitor.service.RedisService; | ||||
|  | @ -58,6 +59,7 @@ public class AuthenticationController { | |||
| 
 | ||||
|     @Log("用户登录") | ||||
|     @ApiOperation("登录授权") | ||||
|     @AnonymousAccess | ||||
|     @PostMapping(value = "/login") | ||||
|     public ResponseEntity login(@Validated @RequestBody AuthUser authorizationUser, HttpServletRequest request){ | ||||
| 
 | ||||
|  | @ -96,6 +98,7 @@ public class AuthenticationController { | |||
|     } | ||||
| 
 | ||||
|     @ApiOperation("获取验证码") | ||||
|     @AnonymousAccess | ||||
|     @GetMapping(value = "/code") | ||||
|     public ImgResult getCode(){ | ||||
|         // 算术类型 https://gitee.com/whvse/EasyCaptcha
 | ||||
|  | @ -110,6 +113,7 @@ public class AuthenticationController { | |||
|     } | ||||
| 
 | ||||
|     @ApiOperation("退出登录") | ||||
|     @AnonymousAccess | ||||
|     @DeleteMapping(value = "/logout") | ||||
|     public ResponseEntity logout(HttpServletRequest request){ | ||||
|         onlineUserService.logout(jwtTokenUtil.getToken(request)); | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ package me.zhengjie.rest; | |||
| import io.swagger.annotations.Api; | ||||
| import io.swagger.annotations.ApiOperation; | ||||
| import lombok.extern.slf4j.Slf4j; | ||||
| import me.zhengjie.annotation.AnonymousAccess; | ||||
| import me.zhengjie.aop.log.Log; | ||||
| import me.zhengjie.domain.AlipayConfig; | ||||
| import me.zhengjie.domain.vo.TradeVo; | ||||
|  | @ -74,6 +75,7 @@ public class AliPayController { | |||
| 
 | ||||
|     @ApiIgnore | ||||
|     @GetMapping("/return") | ||||
|     @AnonymousAccess | ||||
|     @ApiOperation("支付之后跳转的链接") | ||||
|     public ResponseEntity<String> returnPage(HttpServletRequest request, HttpServletResponse response){ | ||||
|         AlipayConfig alipay = alipayService.find(); | ||||
|  | @ -96,6 +98,7 @@ public class AliPayController { | |||
| 
 | ||||
|     @ApiIgnore | ||||
|     @RequestMapping("/notify") | ||||
|     @AnonymousAccess | ||||
|     @ApiOperation("支付异步通知(要公网访问),接收异步通知,检查通知内容app_id、out_trade_no、total_amount是否与请求中的一致,根据trade_status进行后续业务处理") | ||||
|     public ResponseEntity notify(HttpServletRequest request){ | ||||
|         AlipayConfig alipay = alipayService.find(); | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 dqjdda
						dqjdda