一,sso的用途 ?

1,如果有多个应用系统,用户只需要登录一次就可以访问所有相互信任的应用系统。
不需要每次输入用户名称和用户密码,
也不需要创建并记忆多套用户名称和用户密码。

2,系统管理员只需维护一套统一的用户账号,方便、简单。
而不必管理很多套的用户账号。

3, 如果需要开发新的应用系统,可以直接使用单点登录平台的用户认证服务,简化开发流程。

4,oauth和sso的区别:

oauth2解决的是服务提供方(微信等)给第三方应用授权的问题,
   sso解决的是大型系统中各个子系统如何共享登陆状态的问题

说明:刘宏缔的架构森林是一个专注架构的博客,地址:https://www.cnblogs.com/architectforest

对应的源码可以访问这里获取: https://github.com/liuhongdi/

说明:作者:刘宏缔 邮箱: 371125307@qq.com

二,演示项目的相关信息

1,项目地址:

https://github.com/liuhongdi/securityssojwt

2,功能说明:

演示了基于oauth2实现sso

3,项目结构:如图:

三,配置文件说明

1,ssoserver的 pom.xml

        <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--security-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--oauth2-->
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.5.0.RELEASE</version>
</dependency>
<!--jwt-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-jwt</artifactId>
<version>1.1.1.RELEASE</version>
</dependency> <!--jaxb-->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-core</artifactId>
<version>2.3.0</version>
</dependency>
<dependency>
<groupId>javax.activation</groupId>
<artifactId>activation</artifactId>
<version>1.1.1</version>
</dependency>

2,ssoclient1的 pom.xml

        <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--security-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--oauth2-->
<dependency><groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.5.0.RELEASE</version>
</dependency>
<!--jwt-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-jwt</artifactId>
<version>1.1.1.RELEASE</version>
</dependency>
<!--oauth2 autoconfigure-->
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.3.3.RELEASE</version>
</dependency>

3,ssoclient2的 pom.xml

        <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--security-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--oauth2-->
<dependency><groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.5.0.RELEASE</version>
</dependency>
<!--jwt-->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-jwt</artifactId>
<version>1.1.1.RELEASE</version>
</dependency>
<!--oauth2 autoconfigure-->
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<version>2.3.3.RELEASE</version>
</dependency>

4,ssoserver的application.properties

server.port = 8080
server.servlet.context-path = /server
spring.security.user.password=123456 #error
server.error.include-stacktrace=always
#log
logging.level.org.springframework.web=trace
logging.level.org.springframework.security=debug

5,ssoclient1的application.properties

security.oauth2.client.client-id=client1
security.oauth2.client.client-secret=client1secrect
#需要认证时候跳转的地址
security.oauth2.client.user-authorization-uri=http://127.0.0.1:8080/server/oauth/authorize
#请求令牌地址
security.oauth2.client.access-token-uri=http://127.0.0.1:8080/server/oauth/token
#解析
security.oauth2.resource.jwt.key-uri=http://127.0.0.1:8080/server/oauth/token_key
#security.oauth2.resource.jwt.key-value=imooc
#sso
server.port=8081
server.servlet.context-path=/client1

6,ssoclient2的application.properties

security.oauth2.client.client-id=client2
security.oauth2.client.client-secret=client2secrect
#需要认证时候跳转的地址
security.oauth2.client.user-authorization-uri=http://127.0.0.1:8080/server/oauth/authorize
#请求令牌地址
security.oauth2.client.access-token-uri=http://127.0.0.1:8080/server/oauth/token
#解析
security.oauth2.resource.jwt.key-uri=http://127.0.0.1:8080/server/oauth/token_key
#sso
server.port=8082
server.servlet.context-path=/client2

四,java代码说明:

1,ssoserver的WebSecurityConfig.java

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Resource
private SsoUserDetailsService ssoUserDetailsService; @Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
} @Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(ssoUserDetailsService).passwordEncoder(passwordEncoder());
} @Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin().and().authorizeRequests().anyRequest().authenticated();
}
}

2,ssoserver的SsoUserDetailsService.java:

@Component
public class SsoUserDetailsService implements UserDetailsService { @Autowired
private PasswordEncoder passwordEncoder; //本来应该从数据库加载数据,此处供仅演示
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
System.out.println("----------------------loadUserByUsername");
if (username.equals("laoliu") == false) {
throw new UsernameNotFoundException("用户名不存在");
}
return new User(username, passwordEncoder.encode("123456"),
AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER"));
}
}

3,ssoserver的SsoAuthorizationServerConfig.java:

@Configuration
@EnableAuthorizationServer
public class SsoAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { //配置供访问的客户端的账户
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
// 注册一个客户端,设置名称
.withClient("client1")
// 设置客户端阴匙
.secret(new BCryptPasswordEncoder().encode("client1secrect"))
// 对应客户端登录请求URI
.redirectUris("http://127.0.0.1:8081/client1/login")
// 授权方式
.authorizedGrantTypes("authorization_code", "password", "refresh_token")
// 授权范围
.scopes("all")
// 是否自动同意,如果采用非自动同意,则需要用户手动授权
.autoApprove(true)
.and().
withClient("client2")
.redirectUris("http://127.0.0.1:8082/client2/login")
.secret(new BCryptPasswordEncoder().encode("client2secrect"))
.authorizedGrantTypes("authorization_code", "password", "refresh_token")
.scopes("all")
.autoApprove(true);
} @Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(jwtTokenStore()).accessTokenConverter(jwtAccessTokenConverter());
} @Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.tokenKeyAccess("isAuthenticated()");
} @Bean
public TokenStore jwtTokenStore() {
return new JwtTokenStore(jwtAccessTokenConverter());
} @Bean
public JwtAccessTokenConverter jwtAccessTokenConverter(){
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
//指定signkey
converter.setSigningKey("liuhongdi");
return converter;
}
}

4,ssoclient1的HomeController.java

@Controller
@RequestMapping("/home")
public class HomeController {
//查看登录后的用户信息
@RequestMapping("/session")
@ResponseBody
public String getsession(){
//session
String userone = SessionUtil.getCurrentUserName();
System.out.println("user:"+userone);
if (userone == null) {
return "not login";
} else {
return userone;
}
}
}

5,ssoclient1的SessionUtil.java

public class SessionUtil {
//得到security所保存的用户
public static String getCurrentUserName(){
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication.isAuthenticated() && !(authentication instanceof AnonymousAuthenticationToken)) {
Object principal = authentication.getPrincipal();
//System.out.println(principal);
if (principal instanceof String) {
return (String)principal;
} else if (principal instanceof UserDetails) {
String currentuser = ((UserDetails) principal).getUsername();
return currentuser;
} else {
//System.out.println("not instanceof UserDetails");
}
return null;
}
return null;
}
}

6,其他非关键代码可访问github查看

五,测试效果

1,按以下顺序启动三个模块:

ssoserver

ssoclient1

ssoclient2

2,先访问client1,

http://127.0.0.1:8081/client1/home/session

会跳转到:

http://127.0.0.1:8080/server/login

如图:

我们输入用户名 laoliu,密码 123456

这个是写死在代码中的演示账号

登录后会跳转到:

这个url会打印当前登录用户的用户名

我们新打开一个标签页:

http://127.0.0.1:8082/client2/home/session

我们之前并未从client2登录,查看效果:

可以看到也已经登录

3,通过html页面跳转访问:

http://127.0.0.1:8081/client1/index.html

返回:

点击 访问client2 的链接

可正常访问

六,查看spring boot版本

  .   ____          _            __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.3.3.RELEASE)

spring boot:spring security+oauth2+sso+jwt实现单点登录(spring boot 2.3.3)的更多相关文章

  1. 使用Spring Security OAuth2进行简单的单点登录

    1.概述 在本教程中,我们将讨论如何使用Spring Security OAuth和Spring Boot实现SSO - 单点登录. 我们将使用三个单独的应用程序: 授权服务器 - 这是中央身份验证机 ...

  2. Spring Security OAuth2 SSO

    通常公司肯定不止一个系统,每个系统都需要进行认证和权限控制,不可能每个每个系统都自己去写,这个时候需要把登录单独提出来 登录和授权是统一的 业务系统该怎么写还怎么写 最近学习了一下Spring Sec ...

  3. Spring Security OAuth2 SSO 单点登录

    基于 Spring Security OAuth2 SSO 单点登录系统 SSO简介 单点登录(英语:Single sign-on,缩写为 SSO),又译为单一签入,一种对于许多相互关连,但是又是各自 ...

  4. 基于spring boot2.0+spring security +oauth2.0+ jwt微服务架构

    github地址:https://github.com/hankuikuide/microservice-spring-security-oauth2 项目介绍 该项目是一个演示项目,主要演示了,基于 ...

  5. 【SpringSecurityOAuth2】源码分析@EnableOAuth2Sso在Spring Security OAuth2 SSO单点登录场景下的作用

    目录 一.从Spring Security OAuth2官方文档了解@EnableOAuth2Sso作用 二.源码分析@EnableOAuth2Sso作用 @EnableOAuth2Client OA ...

  6. Spring Security构建Rest服务-1300-Spring Security OAuth开发APP认证框架之JWT实现单点登录

    基于JWT实现SSO 在淘宝( https://www.taobao.com )上点击登录,已经跳到了 https://login.taobao.com,这是又一个服务器.只要在淘宝登录了,就能直接访 ...

  7. springBoot整合spring security+JWT实现单点登录与权限管理--筑基中期

    写在前面 在前一篇文章当中,我们介绍了springBoot整合spring security单体应用版,在这篇文章当中,我将介绍springBoot整合spring secury+JWT实现单点登录与 ...

  8. SSO之CAS单点登录详细搭建教程

    本教程是我个人编写,花费几个小时的时间,给需要学习的人员学习使用,希望能帮助到你们. [环境说明]:本文演示过程在同一个机器上的(也可以在三台实体机器或者三个的虚拟机上),环境如下: windows7 ...

  9. Spring Cloud:Security OAuth2 自定义异常响应

    对于客户端开发或者网站开发而言,调用接口返回有统一的响应体,可以针对性的设计界面,代码结构更加清晰,层次也更加分明. 默认异常响应 在使用 Spring Security Oauth2 登录和鉴权失败 ...

随机推荐

  1. 微信小程序常用样式

    1.设置全局字体样式app.wxss: text{ font-family:MicroSoft yahei; } 2.设置弹性盒子模型: .container{ /*弹性模型*/ display:fl ...

  2. python之ddt模块使用

    一.DDT(数据驱动)简介 Data-Driven Tests(DDT)即数据驱动测试,可以实现不同数据运行同一个测试用例(通过数据的不同来驱动测试结果的不同). ddt本质其实就是装饰器,一组数据一 ...

  3. python中使用token模拟登录

    背景:在接口测试中我们经常是需要一个登陆token,或者获取其他用到的参数来关联下一个接口用到的参数. Token的意义及用法 一.Token的来源: 当客户端多次向服务端请求数据时,服务端就需要多次 ...

  4. pytest(3):pytest运行参数介绍

    前言 pytest 带有很多参数,可以使用 pytest --help  来查看帮助文档,下面介绍几种常用的参数: 无参数 读取路径下所有符合规则的文件,类,方法,函数全部执行.使用方法如下:  py ...

  5. vsCode 设置vue文件标签内的style智能提示

    VS Code 文件->首选项->设置 搜索:files.associations 点击在setting.json中编辑 最后一行添加配置: "files.association ...

  6. JVM强引用、软引用、弱引用、虚引用、终结器引用垃圾回收行为总结

    JVM引用 我们希望能描述这样一类对象: 当内存空间还足够时,则能保留在内存中:如果内存空间在进行垃圾收集后还是很紧张,则可以抛弃这些对象. -[既偏门又非常高频的面试题]强引用.软引用.弱引用.虚引 ...

  7. Node.js 从零开发 web server博客项目[日志]

    web server博客项目 Node.js 从零开发 web server博客项目[项目介绍] Node.js 从零开发 web server博客项目[接口] Node.js 从零开发 web se ...

  8. php处理的图片无法进CDN缓存

    今天发现线上有个问题,线上一个图片域名,在前端已经加了CDN缓存,不落缓存,则用PHP动态实现图片缩放,但经PHP处理过的图片输出后,每次都要从后端读取,后端服务器压力瞬间增加,经分析,PHP中没有作 ...

  9. 现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行?

    Thread t1 = new Thread(new T1()); Thread t2 = new Thread(new T2()); Thread t3 = new Thread(new T3()) ...

  10. 1.5Hadoop的启动