@EnableOAuth2Sso
- Spring Boot+OAuth2 做单点登录,利用 @EnableOAuth2Sso 注解快速实现单点登录功能
auth-server 用来扮演授权服务器+资源服务器的角色
项目创建成功之后,这个模块由于要扮演授权服务器+资源服务器的角色,所以我们先在这个项目的启动类上添加 @EnableResourceServer 注解,表示这是一个资源服务器:
@SpringBootApplication
@EnableResourceServer
public class OauthssoApplication {
public static void main(String[] args) {
SpringApplication.run(OauthssoApplication.class, args);
}
}
接下来授权服务器的配置,由于资源服务器和授权服务器合并在一起,因此授权服务器的配置要省事很多:
@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
PasswordEncoder passwordEncoder;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("javaboy")
.secret(passwordEncoder.encode("123"))
.autoApprove(true)
.redirectUris("http://localhost:1112/login", "http://localhost:1113/login")
.scopes("user")
.accessTokenValiditySeconds(7200)
.authorizedGrantTypes("authorization_code");
}
}
接下来我们再来配置 Spring Security
@Configuration
@Order(1)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/login.html", "/css/**", "/js/**", "/images/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatchers()
.antMatchers("/login")
.antMatchers("/oauth/authorize")
.and()
.authorizeRequests().anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login.html")
.loginProcessingUrl("/login")
.permitAll()
.and()
.csrf().disable();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("sang")
.password(passwordEncoder().encode("123"))
.roles("admin");
}
}
- 首先提供一个 BCryptPasswordEncoder 的实例,用来做密码加解密用。
- 由于我自定义了登录页面,所以在 WebSecurity 中对这些静态资源方形。
- HttpSecurity 中,我们对认证相关的端点放行,同时配置一下登录页面和登录接口。
- AuthenticationManagerBuilder 中提供一个基于内存的用户(小伙伴们可以根据 Spring Security 系列第 7 篇文章自行调整为从数据库加载)。
- 另外还有一个比较关键的地方,因为资源服务器和授权服务器在一起,所以我们需要一个 @Order 注解来提升 Spring Security 配置的优先级。
SecurityConfig 和 AuthServerConfig 都是授权服务器需要提供的东西
接下来,我们还需要提供一个暴露用户信息的接口(如果将授权服务器和资源服务器分开,这个接口将由资源服务器提供)
@RestController
public class UserController {
@GetMapping("/user")
public Principal getCurrentUser(Principal principal) {
return principal;
}
}
客户端创建
创建一个名为 client1 的 Spring Boot 项目,创建名为Cloud Security , Cloud Oauth , Spring boot Web
- 项目创建成功之后,配置 Spring Security:
@Configuration
@EnableOAuth2Sso
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated().and().csrf().disable();
}
}
这段配置很简单,就是说我们 client1 中所有的接口都需要认证之后才能访问,另外添加一个 @EnableOAuth2Sso 注解来开启单点登录功能。
接下来我们在 client1 中再来提供一个测试接口:
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
return authentication.getName() + Arrays.toString(authentication.getAuthorities().toArray());
}
}
这个测试接口返回当前登录用户的姓名和角色信息。
接下来我们需要在 client1 的 application.properties 中配置 oauth2 的相关信息:
security.oauth2.client.client-secret=123
security.oauth2.client.client-id=osvue
security.oauth2.client.user-authorization-uri=http://localhost:1111/oauth/authorize
security.oauth2.client.access-token-uri=http://localhost:1111/oauth/token
security.oauth2.resource.user-info-uri=http://localhost:1111/user
server.port=1112
server.servlet.session.cookie.name=s1
- client-secret 是客户端密码。
- client-id 是客户端 id。
- user-authorization-uri 是用户授权的端点。
- access-token-uri 是获取令牌的端点。
- user-info-uri 是获取用户信息的接口(从资源服务器上获取)。
- 最后再配置一下端口,然后给 cookie 取一个名字。
如此之后,我们的 client1 就算是配置完成了。
按照相同的方式,我们再来配置一个 client2,client2 和 client1 一模一样,就是 cookie 的名字不同(随意取,不相同即可)。