系统采用前后端分离的架构,采用OAuth2协议是很自然的事情。
下面开始实战,主要依赖以下两个组件:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId></dependency><dependency> <groupId>org.springframework.security.oauth</groupId> <artifactId>spring-security-oauth2</artifactId></dependency>
例外还要配置两个Config:
一、认证服务器
@Configuration@EnableAuthorizationServerpublic class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter { @Autowired private UserApprovalHandler userApprovalHandler; @Autowired private AuthenticationManager authenticationManager; @Autowired private TokenStore tokenStore; @Autowired private MyUserService userService; @Autowired private ClientDetailsService clientDetailsService; @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient("aizoukeji")// .authorizedGrantTypes("password", "authorization_code", "implicit") .authorizedGrantTypes("password") .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT") .scopes("read", "write", "trust") .secret("18657189775") .accessTokenValiditySeconds(60 * 2);//Access token is only valid for 2 minutes.// refreshTokenValiditySeconds(600);//Refresh token is only valid for 10 minutes. } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.tokenStore(tokenStore) .userApprovalHandler(userApprovalHandler) .authenticationManager(authenticationManager) .userDetailsService(userService); } @Bean public TokenStore tokenStore() { return new InMemoryTokenStore(); } @Bean @Autowired public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore){ TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler(); handler.setTokenStore(tokenStore); handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService)); handler.setClientDetailsService(clientDetailsService); return handler; } @Bean @Autowired public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception { TokenApprovalStore store = new TokenApprovalStore(); store.setTokenStore(tokenStore); return store; }}
二、资源服务器
@Configuration@EnableResourceServerpublic class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { private static final String RESOURCE_ID = "my_rest_api"; @Override public void configure(ResourceServerSecurityConfigurer resources) { resources.resourceId(RESOURCE_ID).stateless(true); } @Override public void configure(HttpSecurity http) throws Exception {// http.requestMatchers().antMatchers("/**")// .and()// .authorizeRequests().antMatchers("/v1/**").authenticated()// .and()// .exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler()); http.authorizeRequests().antMatchers("/v1/**").authenticated() .and() .exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler()); }}
踩过的坑
一开始一直在配置WebSecurityConfigurerAdapter,其实这个跟ResourceServerConfigurerAdapter是冲突的,如果用OAuth来做认证的话,那么只要配置ResourceServerConfigurerAdapter就可以了
延伸
Spring OAuth中有个SSO注解,可以帮助实现单点登录。等项目发展起来以后,我们可以用这个来实现账号的统一授权。
时间: 2024-08-25 12:36:25