点击上方蓝色字体,选择“标星公众号”
优质文章,第一时间送达
上一篇:这300G的Java资料是我师傅当年给我的,免费分享给大家
下一篇:昨天分享资料不小心把百度网盘深处的秘密泄露了
作者:半夜菊花茶
来源:jianshu.com/p/d94bb118aa43
1. 概述
本文简要总结一下如果使用Spring Security OAuth和Spring Boot来实现SSO,文末有样例代码。
整个工程包括三个独立的应用,一个认证服务和两个客户端应用,结构非常简单。当一个用户访问客户端应用中被防护的API时,系统会被自动重定向到认证服务,之后我们使用OAuth2.0的Authorization code授权方式来实现认证授权。
2. 客户端APP
我们先从客户端应用入手,使用Spring Boot可以最大程度简化配置
2.1 Maven依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-securityartifactId>
dependency>
<dependency>
<groupId>org.springframework.security.oauthgroupId>
<artifactId>spring-security-oauth2artifactId>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
<dependency>
<groupId>org.thymeleaf.extrasgroupId>
<artifactId>thymeleaf-extras-springsecurity4artifactId>
dependency>2.2 安全配置
客户端的安全配置如下:
@Configuration
@EnableOAuth2Sso
public class UiSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**")
.authorizeRequests()
.antMatchers("/", "/login**")
.permitAll()
.anyRequest()
.authenticated();
}
}配置最核心的部分是 @EnableOAuth2Sso注解来开启SSO。这里要注意,我们需要重写WebSecurityConfigurerAdapter 否则所有的路径都会受到SSO的保护,这样无论用户访问哪个页面都会被重定向到登录页面,在这个例子里,index和login页面是唯一不需要被防护的。
最后,我们定义一个RequestContextListener bean来处理request scopes。
application.yml:
server:
port: 8082
context-path: /ui
session:
cookie:
name: UISESSION
security:
basic:
enabled: false
oauth2:
client:
clientId: SampleClientId
clientSecret: secret
accessTokenUri: http://localhost:8081/auth/oauth/token
userAuthorizationUri: http://localhost:8081/auth/oauth/authorize
resource:
userInfoUri: http://localhost:8081/auth/user/me
spring:
thymeleaf:
cache: false说明:
我们禁用了default Basic Authentication
accessTokenUri 是获取访问令牌的URL
userAuthorizationUri是授权用户被重定向的目标URL
userInfoUri是用户终端访问用户信息的URL
在这个case里,认证服务是我们自己建设的,但是在实际的应用场景下认证服务往往是第三方提供的比如Facebook 或者 gitHub
2.3 前端
前端并非本文的重点,这里简单提一下。客户端有一个非常简单的前端页面
index.html:
<h1>Spring Security SSOh1>
<a href="securedPage">Logina>securedPage.html:
<h1>Secured Pageh1>
Welcome, <span th:text="${#authentication.name}">Namespan>securedPage.html需要用户通过授权才能访问,如果一个未授权的用户访问这个页面,他会被重定向到login页面3. 认证服务器
3.1 Maven依赖
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.springframework.security.oauthgroupId>
<artifactId>spring-security-oauth2artifactId>
dependency>3.2 OAuth配置
本例中我们把AS(认证服务)器和RS放(资源服务器)在一个实例中部署。
RS配置如下
@EnableResourceServer
public class AuthorizationServerApplication extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(AuthorizationServerApplication.class, args);
}
}AS配置如下:
@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("SampleClientId")
.secret("secret")
.authorizedGrantTypes("authorization_code")
.scopes("user_info")
.autoApprove(true) ;
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManager);
}
}这里我们只开启authorization_code授权模式,另外这里注意到autoApprove=true,这意味着用户不会被重定向到授权的页面,也不需要手动给请求授权。
3.3 安全配置
这里需要定义一个简单的认证机制
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatchers()
.antMatchers("/login", "/oauth/authorize")
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin().permitAll();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.parentAuthenticationManager(authenticationManager)
.inMemoryAuthentication()
.withUser("john").password("123").roles("USER");
}
}注意,我们用了in-memory认证,这里只是做一个简单的例子,我们直接把账号密码写到内存里了,真正使用的时候这里要换成自定义的userDetailsService.
3.4 用户终端
一个很简单的返回JSON消息的接口
@RestController
public class UserController {
@GetMapping("/user/me")
public Principal user(Principal principal) {
return principal;
}
}完整代码: http://suo.im/6xwNoD参考资料:
http://blog.csdn.net/j754379117/article/details/70175198
http://www.baeldung.com/sso-spring-security-oauth2
说句题外话,springboot全家桶技术交流群可以加我微信,但是坑位有限哦,由于忙于工作,有时不能及时回复大家,请多包涵。
猜你喜欢1、Mybatis的这些坑!把我坑惨了!
2、一份不可多得的 Lombok 学习指南
3、为什么说++i比i++效率高?
4、ZooKeeper基本原理
5、在 IntelliJ IDEA 中使用 Git,太方便了!
6、Redis实战--使用Jedis实现百万数据秒级插入
7、7 个显著提升编码效率的IntelliJ IDEA必备插件
8、免费版的 IDEA 为啥不能使用 Tomcat ?
强烈推荐一位大佬的公众号

好文章,我在看❤️