Springboot,springcloud,spring secutity,spring ouath2都需要有明确的版本声明,对于不同版本的类库,实现上也有很大的区别,不同版本的授权是不能通用的。
springboot+springcloud
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.0.4.RELEASE</version> <relativePath/> </parent> <properties> <spring-cloud.version>Finchley.RELEASE</spring-cloud.version> <spring-cloud-alibaba.version>2.0.2.RELEASE</spring-cloud-alibaba.version> <spring-cloud-starter-oauth2.version>2.0.0.RELEASE</spring-cloud-starter-oauth2.version> <spring-security-oauth2.version>2.3.3.RELEASE</spring-security-oauth2.version> <spring-boot-starter-security.version>2.0.0.RELEASE</spring-boot-starter-security.version> </properties> <dependencyManagement> <dependencies> <!--spring cloud 版本--> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
gateway,oauth,system等服务添加引用
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> <version>${spring-boot-starter-security.version}</version> </dependency> <dependency> <groupId>org.springframework.security.oauth</groupId> <artifactId>spring-security-oauth2</artifactId> <version>${spring-security-oauth2.version}</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-oauth2</artifactId> <version>${spring-cloud-starter-oauth2.version}</version> </dependency>
@EnableWebFluxSecurity public class GatewaySecurityConfig { @Bean SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity serverHttpSecurity) throws Exception { serverHttpSecurity .csrf().disable(); serverHttpSecurity.cors(); return serverHttpSecurity.build(); } }
AuthorizationServerConfig继承AuthorizationServerConfigurerAdapter 用来配置客户端详情服务(ClientDetailsService),客户端详情信息在这里进行初始化,你能够把客户端详情信息写死在这里或者是通过数据库来存储调取详情信息。
ResourceServerConfig它上面添加注解@EnableResourceServer帮我们加入了 org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter,该filter帮我们从request里解析出access_token并通过org.springframework.security.oauth2.provider.token.DefaultTokenServices根据access_token和认证服务器配置里的TokenStore从redis或者jwt里解析出用户注意认证中心的@EnableResourceServer和别的微服务里的@EnableResourceServer有些不同别的微服务是通过org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoTokenServices来获取用户的.
@Configuration @EnableResourceServer public class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http.requestMatcher(new OAuth2RequestedMatcher()).authorizeRequests() .antMatchers(PermitAllUrl.permitAllUrl()).permitAll() // 放开权限的url .anyRequest().authenticated(); } /** * 判断来源请求是否包含oauth2授权信息<br> * url参数中含有access_token,或者header里有Authorization */ private static class OAuth2RequestedMatcher implements RequestMatcher { @Override public boolean matches(HttpServletRequest request) { // 请求参数中包含access_token参数 if (request.getParameter(OAuth2AccessToken.ACCESS_TOKEN) != null) { return true; } // 头部的Authorization值以Bearer开头 String auth = request.getHeader("Authorization"); if (auth != null) { return auth.startsWith(OAuth2AccessToken.BEARER_TYPE); } return false; } } }
SecurityConfig,这个bean主要设置用户获取接口和加密规则
@EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired public UserDetailsService userDetailsService; @Autowired private BCryptPasswordEncoder passwordEncoder; @Value("${pkulaw.token.redis}") private Boolean tokenRedis; @Value("${pkulaw.tokenExpireTime}") private Integer tokenExpireTime; @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder); } /** * 认证管理 * * @return 认证管理对象 * @throws Exception 认证异常信息 */ @Bean @Override public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } /** * http安全配置 * * @param http http安全对象 * @throws Exception http安全异常信息 */ @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() .antMatchers(PermitAllUrl.permitAllUrl()).permitAll() // 放开权限的url .anyRequest().authenticated().and() .httpBasic().and().csrf().disable(); }
UserDetailServiceImpl用来获取用户信息,通过通过feign获取system里的接口
@Service("userDetailsService") public class UserDetailServiceImpl implements UserDetailsService { @Autowired StringRedisTemplate redisTemplate; @Autowired ObjectMapper objectMapper; @Autowired private UserClient userClient; @Autowired private RedisUtil redisUtil; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { String flagKey = "loginFailFlag:" + username; String value = redisTemplate.opsForValue().get(flagKey); Long timeRest = redisTemplate.getExpire(flagKey, TimeUnit.MINUTES); if (StrUtil.isNotBlank(value)) { //超过限制次数 System.out.println("登录错误次数超过限制,请" + timeRest + "分钟后再试"); throw new PkuLawException("登录错误次数超过限制,请" + timeRest + "分钟后再试"); } User user = userClient.findByUsername(username); //持久化到redis redisUtil.set(RedisConstant.USER + username, user); return new SecurityUserDetails(user); } }
system也是资源服务的一种,主要提供用户服务,每个资源服务都有一个ResourceServerConfig的bean,用来规定你的资源开放策略。
/** * 资源服务配置 */ @EnableResourceServer @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Override public void configure(ResourceServerSecurityConfigurer resources) throws Exception { super.configure(resources); } @Override public void configure(HttpSecurity http) throws Exception { http.csrf().disable().exceptionHandling() .authenticationEntryPoint( (request, response, authException) -> response.sendError( HttpServletResponse.SC_UNAUTHORIZED)) .and().authorizeRequests() .antMatchers(PermitAllUrl .permitAllUrl("/company/register","/druid/**","/file/view/**","/**/users-anon/**")).permitAll() // 放开权限的url .anyRequest().authenticated() .and().httpBasic() .and().addFilterBefore(new BeforeTokenFilter(), AbstractPreAuthenticatedProcessingFilter.class) ; http.headers().frameOptions().sameOrigin(); } @Bean public BCryptPasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
通过在yml里对oauth2的配置,来获取当前oauth里的登录信息,并把登陆状态写到自己服务的HTTP请求里,这个过程是oauth框架帮我们实现的。
security: oauth2: resource: user-info-uri: http://localhost:6660/pkulaw/oauth/user-me #授权服务的获取当前用户接口,它的返回值是Authentication类型,它会把返回值写到当前服务的请求头里 prefer-token-info: false
这篇文章主要记录了oauth2搭建的过程。
原文链接:https://www.cnblogs.com/lori/p/13398048.html