新建一个模块,命名为stockservice,使用OAuth2进行服务保护,写两个API接口,一个需要验证,一个不需要验证。
1、添加maven依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-consul-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> </dependency> <dependency> <groupId>com.example.consul</groupId> <artifactId>common</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency>
2、配置文件
server: port: 8803 spring: application: name: stockservice profiles: active: dev cloud: consul: host: localhost port: 8500 discovery: service-name: stockservice datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://127.0.0.1:3306/springcloud?useUnicode=true&characterEncoding=utf8&useSSL=false&zeroDateTimeBehavior=convertToNull password: root username: root
3、启动类
@SpringBootApplication @EnableDiscoveryClient @ComponentScan(basePackages = {"com.example.consul.stockservice","com.example.consul.common"}) public class StockserviceApplication { public static void main(String[] args) { SpringApplication.run(StockserviceApplication.class, args); } }
4、配置资源服务
@Configuration @EnableResourceServer public class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Autowired private JWTConfig jwtConfig; /** * 权限认证失败的异常 */ @Bean public AccessDeniedHandler getAccessDeniedHandler() { return new ResourceAccessDeniedHandler(); } /** * 未经授权异常 * @return */ @Bean public AuthenticationEntryPoint getAuthenticationEntryPoint() { return new ResourceAuthenticationEntryPoint(); } @Override public void configure(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeRequests() .antMatchers("/stock/queryStock").permitAll() .antMatchers("/**").authenticated(); } /** * 自定义token认证授权 * @param resources * @throws Exception */ @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { resources.tokenStore(tokenStore()) .accessDeniedHandler(getAccessDeniedHandler()) .authenticationEntryPoint(getAuthenticationEntryPoint()); } /** * 自定义验证token * 和认证服务器保持一致 * @return */ @Bean public TokenStore tokenStore() { return new JwtTokenStore(jwtTokenEnhancer()); } /** * jwt签名秘钥 * @return */ @Bean public JwtAccessTokenConverter jwtTokenEnhancer() { JwtAccessTokenConverter jwtAccessTokenConverter = new JwtAccessTokenConverter(); jwtAccessTokenConverter.setSigningKey(jwtConfig.getSigningKey()); return jwtAccessTokenConverter; } }
/** * 自定义未授权返回信息 */ @Component public class ResourceAuthenticationEntryPoint implements AuthenticationEntryPoint { @Override public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException { HashMap<String, String> map = new HashMap<>(); map.put("code", "500"); map.put("msg", "未授权服务"); map.put("uri", httpServletRequest.getRequestURI()); httpServletResponse.setStatus(HttpServletResponse.SC_FORBIDDEN); httpServletResponse.setCharacterEncoding("utf-8"); httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE); ObjectMapper objectMapper = new ObjectMapper(); String resBody = objectMapper.writeValueAsString(map); PrintWriter printWriter = httpServletResponse.getWriter(); printWriter.print(resBody); printWriter.flush(); printWriter.close(); } }
/** * 自定义权限不足信息 */ @Component public class ResourceAccessDeniedHandler implements AccessDeniedHandler { @Override public void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException, ServletException { HashMap<String, String> map = new HashMap<>(); map.put("code", "500"); map.put("msg", "权限不足"); map.put("uri", httpServletRequest.getRequestURI()); httpServletResponse.setStatus(HttpServletResponse.SC_FORBIDDEN); httpServletResponse.setCharacterEncoding("utf-8"); httpServletResponse.setContentType(MediaType.APPLICATION_JSON_VALUE); ObjectMapper objectMapper = new ObjectMapper(); String resBody = objectMapper.writeValueAsString(map); PrintWriter printWriter = httpServletResponse.getWriter(); printWriter.print(resBody); printWriter.flush(); printWriter.close(); } }
5、API接口
@RestController @RequestMapping("stock") public class StockController { @PostMapping("/info") @PreAuthorize("6") public String info() { return "info"; } @GetMapping("/queryStock") public String queryStock() { return "queryStock"; } }
6、接口测试
postman模拟请求http://localhost:8803/stock/queryStock,不使用token,即不用验证,返回queryStock。
postman模拟请求http://localhost:8803/stock/info,不使用token,返回错误信息。
{
"msg": "未进行授权,暂时无法访问",
"code": "500",
"uri": "/stock/info"
}
进行如下设置,通过验证后返回正确的结果: