一,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. 小BUG大原理 | 第一篇:重写WebMvcConfigurationSupport后SpringBoot自动配置失效

    一.背景 公司的项目前段时间发版上线后,测试反馈用户的批量删除功能报错.正常情况下看起来应该是个小BUG,可怪就怪在上个版本正常,且此次发版未涉及用户功能的改动.因为这个看似小BUG我了解到不少未知的 ...

  2. MYsql添加用户、赋予权限

    1.创建新用户 CREATE USER 'admin'@'%' IDENTIFIED BY '123456'; '%' 表示可以远程登录访问.操作 ‘localhost’ 表示只能本地登录访问.操作2 ...

  3. mariadb 2

    mariadb第二章-增删改   MariaDB 数据类型 MariaDB数据类型可以分为数字,日期和时间以及字符串值. 使用数据类型的原则:够用就行, 尽量使用范围小的,而不用大的 常用的数据类型 ...

  4. Git+Gitlab+Ansible的roles实现一键部署Nginx静态网站(4)

    前言 截止目前已经写了<Ansible基础认识及安装使用详解(一)–技术流ken>,<Ansible常用模块介绍及使用(二)–技术流ken><Ansible剧本介绍及使用 ...

  5. hystrix熔断器之线程池

    隔离 Hystrix有两种隔离方式:信号量和线程池. 线程池隔离:对每个command创建一个自己的线程池,执行调用.通过线程池隔离来保证不同调用不会相互干扰和每一个调用的并发限制. 信号量隔热:对每 ...

  6. TKE 集群组建最佳实践

    Kubernetes 版本 Kubernetes 版本迭代比较快,新版本通常包含许多 bug 修复和新功能,旧版本逐渐淘汰,建议创建集群时选择当前 TKE 支持的最新版本,后续出新版本后也是可以支持 ...

  7. windows提权之mimikatz

    mimikatz privilege::debug #提权命令 sekurlsa::logonPasswords #抓取密码 winmine::infos #扫雷作弊 lsadump::lsa /pa ...

  8. [阅读笔记]Attention Is All You Need - Transformer结构

    Transformer 本文介绍了Transformer结构, 是一种encoder-decoder, 用来处理序列问题, 常用在NLP相关问题中. 与传统的专门处理序列问题的encoder-deco ...

  9. JVM性能调优(2) —— 垃圾回收器和回收策略

    一.垃圾回收机制 1.为什么需要垃圾回收 Java 程序在虚拟机中运行,是会占用内存资源的,比如创建的对象.加载的类型数据等,而且内存资源都是有限的.当创建的对象不再被引用时,就需要被回收掉,释放内存 ...

  10. PHP图片压缩类,高清无损直接用就ok啦

    这个不完全是我自己写的-_-!,但是好用呀 <?php /** * Created by PhpStorm. * Note:文件介绍 * User: Lynly * Date: 2018/11/ ...