From 858dbd3abf25503e96fad08f89223edb8fd6a043 Mon Sep 17 00:00:00 2001 From: zhuyijun Date: Sun, 18 Sep 2022 23:50:30 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=B5=84=E6=BA=90=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E5=99=A8=E6=8B=A6=E6=88=AA=E4=B8=8ESpring=20Security?= =?UTF-8?q?=E6=8B=A6=E6=88=AA=E4=BC=98=E5=85=88=E7=BA=A7=E9=97=AE=E9=A2=98?= =?UTF-8?q?=EF=BC=8C=E8=B5=84=E6=BA=90=E6=9C=8D=E5=8A=A1=E6=8B=A6=E6=88=AA?= =?UTF-8?q?=E5=99=A8=E4=BC=98=E5=85=88=E7=BA=A7=E9=AB=98=E4=BA=8ESpring=20?= =?UTF-8?q?Security=EF=BC=8C=E9=99=90=E5=88=B6=E8=B5=84=E6=BA=90=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E5=99=A8=E6=8B=A6=E6=88=AA=E4=BD=9C=E7=94=A8=E8=8C=83?= =?UTF-8?q?=E5=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../handler/ResourceAccessDeniedHandler.java | 33 +++++++++++++++++ .../ResourceAuthenticationEntryPoint.java | 32 ++++++++++++++++ .../oauth/resource/ResourceServerConfig.java | 9 ++++- .../handler/ResourceAccessDeniedHandler.java | 33 +++++++++++++++++ .../ResourceAuthenticationEntryPoint.java | 32 ++++++++++++++++ .../config/security/ResourceServerConfig.java | 37 +++++++++++++------ .../security/WebSecurityConfiguration.java | 12 +++--- .../src/main/resources/bootstrap.yml | 1 + 8 files changed, 168 insertions(+), 21 deletions(-) create mode 100644 zyjblogs-oauth-spring-boot-starter/src/main/java/cn/zyjblogs/starter/oauth/handler/ResourceAccessDeniedHandler.java create mode 100644 zyjblogs-oauth-spring-boot-starter/src/main/java/cn/zyjblogs/starter/oauth/handler/ResourceAuthenticationEntryPoint.java create mode 100644 zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/handler/ResourceAccessDeniedHandler.java create mode 100644 zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/handler/ResourceAuthenticationEntryPoint.java diff --git a/zyjblogs-oauth-spring-boot-starter/src/main/java/cn/zyjblogs/starter/oauth/handler/ResourceAccessDeniedHandler.java b/zyjblogs-oauth-spring-boot-starter/src/main/java/cn/zyjblogs/starter/oauth/handler/ResourceAccessDeniedHandler.java new file mode 100644 index 0000000..1984194 --- /dev/null +++ b/zyjblogs-oauth-spring-boot-starter/src/main/java/cn/zyjblogs/starter/oauth/handler/ResourceAccessDeniedHandler.java @@ -0,0 +1,33 @@ +package cn.zyjblogs.starter.oauth.handler; + +import cn.zyjblogs.starter.common.entity.response.HttpCode; +import cn.zyjblogs.starter.common.entity.response.ResponseResult; +import org.codehaus.jackson.map.ObjectMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.MediaType; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.web.access.AccessDeniedHandler; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author zhuyijun + */ + +public class ResourceAccessDeniedHandler implements AccessDeniedHandler { + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + private static final Logger log = LoggerFactory.getLogger(ResourceAccessDeniedHandler.class); + + @Override + public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException { + log.error("禁止访问 {}", e.getMessage()); + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + OBJECT_MAPPER.writeValue(response.getOutputStream(), + ResponseResult.error(HttpCode.FORBIDDEN, "无权访问该资源")); + + } +} diff --git a/zyjblogs-oauth-spring-boot-starter/src/main/java/cn/zyjblogs/starter/oauth/handler/ResourceAuthenticationEntryPoint.java b/zyjblogs-oauth-spring-boot-starter/src/main/java/cn/zyjblogs/starter/oauth/handler/ResourceAuthenticationEntryPoint.java new file mode 100644 index 0000000..f893c12 --- /dev/null +++ b/zyjblogs-oauth-spring-boot-starter/src/main/java/cn/zyjblogs/starter/oauth/handler/ResourceAuthenticationEntryPoint.java @@ -0,0 +1,32 @@ +package cn.zyjblogs.starter.oauth.handler; + +import cn.zyjblogs.starter.common.entity.response.HttpCode; +import cn.zyjblogs.starter.common.entity.response.ResponseResult; +import org.codehaus.jackson.map.ObjectMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.MediaType; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author zhuyijun + */ +public class ResourceAuthenticationEntryPoint implements AuthenticationEntryPoint { + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + private static final Logger log = LoggerFactory.getLogger(ResourceAuthenticationEntryPoint.class); + + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException { + log.error("认证失败 {}", e.getMessage()); + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + OBJECT_MAPPER.writeValue(response.getOutputStream(), + ResponseResult.error(HttpCode.UNAUTHORIZED, "认证失败,token无效!")); + + } +} diff --git a/zyjblogs-oauth-spring-boot-starter/src/main/java/cn/zyjblogs/starter/oauth/resource/ResourceServerConfig.java b/zyjblogs-oauth-spring-boot-starter/src/main/java/cn/zyjblogs/starter/oauth/resource/ResourceServerConfig.java index f48ccdd..ccd1ce5 100644 --- a/zyjblogs-oauth-spring-boot-starter/src/main/java/cn/zyjblogs/starter/oauth/resource/ResourceServerConfig.java +++ b/zyjblogs-oauth-spring-boot-starter/src/main/java/cn/zyjblogs/starter/oauth/resource/ResourceServerConfig.java @@ -1,5 +1,7 @@ package cn.zyjblogs.starter.oauth.resource; +import cn.zyjblogs.starter.oauth.handler.ResourceAccessDeniedHandler; +import cn.zyjblogs.starter.oauth.handler.ResourceAuthenticationEntryPoint; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; @@ -30,7 +32,9 @@ public class ResourceServerConfig extends ResourceServerConfigurerAdapter { resources.resourceId(resourceId) // 验证令牌的服务 .tokenStore(tokenStore) - .stateless(true); + .stateless(true) + .accessDeniedHandler(new ResourceAccessDeniedHandler()) + .authenticationEntryPoint(new ResourceAuthenticationEntryPoint()); } @Override @@ -42,7 +46,8 @@ public class ResourceServerConfig extends ResourceServerConfigurerAdapter { .anyRequest() .authenticated() .and() - .csrf().disable(); + .csrf().disable() + .httpBasic(); } } diff --git a/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/handler/ResourceAccessDeniedHandler.java b/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/handler/ResourceAccessDeniedHandler.java new file mode 100644 index 0000000..b5addea --- /dev/null +++ b/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/handler/ResourceAccessDeniedHandler.java @@ -0,0 +1,33 @@ +package cn.zyjblogs.oauth.config.handler; + +import cn.zyjblogs.starter.common.entity.response.HttpCode; +import cn.zyjblogs.starter.common.entity.response.ResponseResult; +import org.codehaus.jackson.map.ObjectMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.MediaType; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.web.access.AccessDeniedHandler; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author zhuyijun + */ + +public class ResourceAccessDeniedHandler implements AccessDeniedHandler { + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + private static final Logger log = LoggerFactory.getLogger(ResourceAccessDeniedHandler.class); + + @Override + public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException { + log.error("禁止访问 {}", e.getMessage()); + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + OBJECT_MAPPER.writeValue(response.getOutputStream(), + ResponseResult.error(HttpCode.FORBIDDEN, "无权访问Oauth资源")); + + } +} diff --git a/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/handler/ResourceAuthenticationEntryPoint.java b/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/handler/ResourceAuthenticationEntryPoint.java new file mode 100644 index 0000000..39e012e --- /dev/null +++ b/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/handler/ResourceAuthenticationEntryPoint.java @@ -0,0 +1,32 @@ +package cn.zyjblogs.oauth.config.handler; + +import cn.zyjblogs.starter.common.entity.response.HttpCode; +import cn.zyjblogs.starter.common.entity.response.ResponseResult; +import org.codehaus.jackson.map.ObjectMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.MediaType; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * @author zhuyijun + */ +public class ResourceAuthenticationEntryPoint implements AuthenticationEntryPoint { + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + private static final Logger log = LoggerFactory.getLogger(ResourceAuthenticationEntryPoint.class); + + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, ServletException { + log.error("认证失败 {}", e.getMessage()); + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + OBJECT_MAPPER.writeValue(response.getOutputStream(), + ResponseResult.error(HttpCode.UNAUTHORIZED, "认证失败!")); + + } +} diff --git a/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/ResourceServerConfig.java b/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/ResourceServerConfig.java index 91af7c6..c38ddc4 100644 --- a/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/ResourceServerConfig.java +++ b/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/ResourceServerConfig.java @@ -1,12 +1,12 @@ package cn.zyjblogs.oauth.config.security; +import cn.zyjblogs.oauth.config.handler.ResourceAccessDeniedHandler; +import cn.zyjblogs.oauth.config.handler.ResourceAuthenticationEntryPoint; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.cloud.context.config.annotation.RefreshScope; import org.springframework.context.annotation.Configuration; -import org.springframework.core.annotation.Order; import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer; import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer; @@ -16,7 +16,7 @@ import org.springframework.security.oauth2.provider.token.TokenStore; @EnableResourceServer @RequiredArgsConstructor @RefreshScope -@Order(100) +//@Order(50) public class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Value("${spring.application.name}") private String resourceId; @@ -27,22 +27,35 @@ public class ResourceServerConfig extends ResourceServerConfigurerAdapter { resources.resourceId(resourceId) // 验证令牌的服务 .tokenStore(tokenStore) - .stateless(true); + .stateless(true) + .accessDeniedHandler(new ResourceAccessDeniedHandler()) + .authenticationEntryPoint(new ResourceAuthenticationEntryPoint()); } + /** + * 资源服务器拦截优先级高于Spring Scurity,限制资源服务器作用范围 + * + * @param http + * @return void + * @author zhuyijun + * @date 2022/9/18 下午10:52 + */ @Override public void configure(HttpSecurity http) throws Exception { - http.sessionManagement() - .sessionCreationPolicy(SessionCreationPolicy.STATELESS) - .and() + http + .csrf() + .disable() + //限制资源服务器作用范围为 "/user/**", "/demo/**" + .requestMatchers().antMatchers("/user/**", "/demo/**").and() + .formLogin().and() .authorizeRequests() - .antMatchers("/user/login", "/login", "/user/refresh/token") - .permitAll() .antMatchers("/webjars/**", "/swagger-ui.html/**", "/swagger-resources/**", "/v2/api-docs/**") .permitAll() - .anyRequest().authenticated() - .and() - .csrf().disable(); + .antMatchers("/login", "/oauth/**", "/user/login", "/user/refresh/token").permitAll() + //以下请求必须认证通过 + .anyRequest() + .authenticated().and() + .httpBasic(); } } diff --git a/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/WebSecurityConfiguration.java b/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/WebSecurityConfiguration.java index d275ae9..17f65aa 100644 --- a/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/WebSecurityConfiguration.java +++ b/zyjblogs-oauth/src/main/java/cn/zyjblogs/oauth/config/security/WebSecurityConfiguration.java @@ -4,7 +4,6 @@ import cn.zyjblogs.oauth.server.user.service.impl.OauthUserDetailsServiceImpl; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.core.annotation.Order; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; @@ -16,7 +15,7 @@ import org.springframework.security.crypto.password.PasswordEncoder; @Configuration @EnableWebSecurity @RequiredArgsConstructor -@Order(1) +//@Order(1) public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { private final OauthUserDetailsServiceImpl userDetailsService; @@ -55,12 +54,11 @@ public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { http.csrf().disable(); //使HttpSecurity接收以"/login/","/oauth/"开头请求, 配置HttpSecurity不阻止swagger页面 http.authorizeRequests() - .antMatchers("/webjars/**", "/swagger-ui.html/**", "/swagger-resources/**", "/v2/api-docs/**") - .permitAll() - .antMatchers("/login", "/oauth/**", "/user/logout", "/user/login", "/user/refresh/token").permitAll() +// .antMatchers("/webjars/**", "/swagger-ui.html/**", "/swagger-resources/**", "/v2/api-docs/**") +// .permitAll() +// .antMatchers("/user/logout", "/login", "/oauth/**", "/user/login", "/user/refresh/token").permitAll() //以下请求必须认证通过 - .anyRequest() - .authenticated() + .anyRequest().authenticated() .and() //允许表单登录 .formLogin() diff --git a/zyjblogs-rbac/src/main/resources/bootstrap.yml b/zyjblogs-rbac/src/main/resources/bootstrap.yml index 171dade..b953b7b 100644 --- a/zyjblogs-rbac/src/main/resources/bootstrap.yml +++ b/zyjblogs-rbac/src/main/resources/bootstrap.yml @@ -27,6 +27,7 @@ spring: logging: config: classpath:logback-spring.xml + #security: # oauth2: # client: