Spring Security 单点登录简单示例详解

Overview

最近在弄单点登录,踩了不少坑,所以记录一下,做了个简单的例子。

目标:认证服务器认证后获取 token,客户端访问资源时带上 token 进行安全验证。

可以直接看源码

关键依赖

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.1.2.RELEASE</version>
    <relativePath/>
</parent>

<dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-security</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-test</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-test</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.security.oauth.boot</groupId>
      <artifactId>spring-security-oauth2-autoconfigure</artifactId>
      <version>2.1.2.RELEASE</version>
    </dependency>
</dependencies>

认证服务器

认证服务器的关键代码有如下几个文件:

AuthServerApplication:

@SpringBootApplication
@EnableResourceServer
public class AuthServerApplication {
  public static void main(String[] args) {
    SpringApplication.run(AuthServerApplication.class, args);
  }

}

AuthorizationServerConfiguration 认证配置:

@Configuration
@EnableAuthorizationServer
class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
  @Autowired
  AuthenticationManager authenticationManager;

  @Autowired
  TokenStore tokenStore;

  @Autowired
  BCryptPasswordEncoder encoder;

  @Override
  public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    //配置客户端
    clients
        .inMemory()
        .withClient("client")
        .secret(encoder.encode("123456")).resourceIds("hi")
        .authorizedGrantTypes("password","refresh_token")
        .scopes("read");
  }

  @Override
  public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    endpoints
        .tokenStore(tokenStore)
        .authenticationManager(authenticationManager);
  }

  @Override
  public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
    //允许表单认证
    oauthServer
        .allowFormAuthenticationForClients()
        .checkTokenAccess("permitAll()")
        .tokenKeyAccess("permitAll()");
  }
}

代码中配置了一个 client,id 是 client,密码 123456authorizedGrantTypespasswordrefresh_token 两种方式。

SecurityConfiguration 安全配置:

@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
  @Bean
  public TokenStore tokenStore() {
    return new InMemoryTokenStore();
  }

  @Bean
  public BCryptPasswordEncoder encoder() {
    return new BCryptPasswordEncoder();
  }

  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication()
        .passwordEncoder(encoder())
        .withUser("user_1").password(encoder().encode("123456")).roles("USER")
        .and()
        .withUser("user_2").password(encoder().encode("123456")).roles("ADMIN");
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    // @formatter:off
    http.csrf().disable()
        .requestMatchers()
        .antMatchers("/oauth/authorize")
        .and()
        .authorizeRequests()
        .anyRequest().authenticated()
        .and()
        .formLogin().permitAll();
    // @formatter:on
  }

  @Override
  @Bean
  public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
  }
}

上面在内存中创建了两个用户,角色分别是 USERADMIN。后续可考虑在数据库或者 Redis 中存储相关信息。

AuthUser 配置获取用户信息的 Controller:

@RestController
public class AuthUser {
    @GetMapping("/oauth/user")
    public Principal user(Principal principal) {
      return principal;
    }

}

application.yml 配置,主要就是配置个端口号:

---
spring:
 profiles:
  active: dev
 application:
  name: auth-server
server:
 port: 8101

客户端配置

客户端的配置比较简单,主要代码结构如下:

application.yml 配置:

---
spring:
 profiles:
  active: dev
 application:
  name: client

server:
 port: 8102
security:
 oauth2:
  client:
   client-id: client
   client-secret: 123456
   access-token-uri: http://localhost:8101/oauth/token
   user-authorization-uri: http://localhost:8101/oauth/authorize
   scope: read
   use-current-uri: false
  resource:
   user-info-uri: http://localhost:8101/oauth/user

这里主要是配置了认证服务器的相关地址以及客户端的 id 和 密码。user-info-uri 配置的就是服务器端获取用户信息的接口。

HelloController 访问的资源,配置了 ADMIN 的角色才可以访问:

@RestController
public class HelloController {
  @RequestMapping("/hi")
  @PreAuthorize("hasRole('ADMIN')")
  public ResponseEntity<String> hi() {
    return ResponseEntity.ok().body("auth success!");
  }
}

WebSecurityConfiguration 相关安全配置:

@Configuration
@EnableOAuth2Sso
@EnableGlobalMethodSecurity(prePostEnabled = true)
class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

  @Override
  public void configure(HttpSecurity http) throws Exception {

    http
        .csrf().disable()
        // 基于token,所以不需要session
       .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
        .authorizeRequests()
        .anyRequest().authenticated();
  }

}

其中 @EnableGlobalMethodSecurity(prePostEnabled = true) 开启后,Spring Security 的 @PreAuthorize,@PostAuthorize 注解才可以使用。

@EnableOAuth2Sso 配置了单点登录。

ClientApplication

@SpringBootApplication
@EnableResourceServer
public class ClientApplication {
  public static void main(String[] args) {
    SpringApplication.run(ClientApplication.class, args);
  }

}

验证

启动项目后,我们使用 postman 来进行验证。

首先是获取 token:

选择 POST 提交,地址为验证服务器的地址,参数中输入 username,password,grant_typescope ,其中 grant_type 需要输入 password

然后在下面等 Authorization 标签页中,选择 Basic Auth,然后输入 client 的 id 和 password。

{
  "access_token": "02f501a9-c482-46d4-a455-bf79a0e0e728",
  "token_type": "bearer",
  "refresh_token": "0e62dddc-4f51-4cb5-81c3-5383fddbb81b",
  "expires_in": 41741,
  "scope": "read"
}

此时就可以获得 access_token 为: 02f501a9-c482-46d4-a455-bf79a0e0e728。需要注意的是这里是用 user_2 获取的 token,即角色是 ADMIN

然后我们再进行获取资源的验证:

使用 GET 方法,参数中输入 access_token,值输入 02f501a9-c482-46d4-a455-bf79a0e0e728

点击提交后即可获取到结果。

如果我们不加上 token ,则会提示无权限。同样如果我们换上 user_1 获取的 token,因 user_1 的角色是 USER,此资源需要 ADMIN 权限,则此处还是会获取失败。

简单的例子就到这,后续有时间再加上其它功能吧,谢谢~

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • spring boot整合Shiro实现单点登录的示例代码

    Shiro是什么 Shiro是一个Java平台的开源权限框架,用于认证和访问授权.具体来说,满足对如下元素的支持: 用户,角色,权限(仅仅是操作权限,数据权限必须与业务需求紧密结合),资源(url). 用户分配角色,角色定义权限. 访问授权时支持角色或者权限,并且支持多级的权限定义. Q:对组的支持? A:shiro默认不支持对组设置权限. Q:是否可以满足对组进行角色分配的需求? A:扩展Realm,可以支持对组进行分配角色,其实就是给该组下的所有用户分配权限. Q:对数据权限的支持? 在业务

  • spring boot 1.5.4 集成shiro+cas,实现单点登录和权限控制

    1.添加maven依赖(先安装好cas-server-3.5.2,安装步骤请查看本文参考文章) <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.2.4</version> </dependency> <dependency> <groupId>

  • SpringMVC拦截器实现单点登录

    单点登录的功能在实际的应用场景中还是很重要的,逻辑上我们也不允许一个用户同时在进行着两个操作,下面就来了解一下SpringMVC的单点登录实现 SpringMVC的拦截器不同于Spring的拦截器,SpringMVC具有统一的入口DispatcherServlet,所有的请求都通过DispatcherServlet,所以只需要在DispatcherServlet上做文章即可,DispatcherServlet也没有代理,同时SpringMVC管理的Controller也不有代理. 1,先探究一个

  • SpringCloud实现SSO 单点登录的示例代码

    前言 作为分布式项目,单点登录是必不可少的,文本基于之前的的博客(猛戳:SpringCloud系列--Zuul 动态路由,SpringBoot系列--Redis)记录Zuul配合Redis实现一个简单的sso单点登录实例 sso单点登录思路: 1.访问分布式系统的任意请求,被Zuul的Filter拦截过滤 2.在run方法里实现过滤规则:cookie有令牌accessToken且作为key存在于Redis,或者访问的是登录页面.登录请求则放行 3.否则,将重定向到sso-server的登录页面且

  • 详解基于Spring Cloud几行配置完成单点登录开发

    单点登录概念 单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一.SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统.登录逻辑如上图 基于Spring 全家桶的实现 技术选型: Spring Boot Spring Cloud Spring Security oAuth2 客户端: maven依赖 <dependency> <groupId>org.springframework.boot</g

  • vue+springboot前后端分离实现单点登录跨域问题解决方法

    最近在做一个后台管理系统,前端是用时下火热的vue.js,后台是基于springboot的.因为后台系统没有登录功能,但是公司要求统一登录,登录认证统一使用.net项目组的认证系统.那就意味着做单点登录咯,至于不知道什么是单点登录的同学,建议去找一下万能的度娘. 刚接到这个需求的时候,老夫心里便不屑的认为:区区登录何足挂齿,但是,开发的过程狠狠的打了我一巴掌(火辣辣的一巴掌)...,所以这次必须得好好记录一下这次教训,以免以后再踩这样的坑. 我面临的第一个问题是跨域,浏览器控制台直接报CORS,

  • 详解spring boot配置单点登录

    概述 企业内部一般都有一套单点登录系统(常用的实现有apereo cas),所有的内部系统的登录认证都对接它.本文介绍spring boot的程序如何对接CAS服务. 常用的安全框架有spring security和apache shiro.shiro的配置和使用相对简单,本文使用shrio对接CAS服务. 配置 新增依赖 pom.xml新增: <properties> <shiro.version>1.2.4</shiro.version> </properti

  • spring + shiro + cas 实现sso单点登录的示例代码

    sso-shiro-cas spring下使用shiro+cas配置单点登录,多个系统之间的访问,每次只需要登录一次,项目源码 系统模块说明 1.cas: 单点登录模块,这里直接拿的是cas的项目改了点样式而已 2.doc: 文档目录,里面有数据库生成语句,采用的是MySQL5.0,数据库名为db_test 3.spring-node-1: 应用1 4.spring-node-2: 应用2 其中node1跟node2都是采用spring + springMVC + mybatis 框架,使用ma

  • Spring Security 单点登录简单示例详解

    Overview 最近在弄单点登录,踩了不少坑,所以记录一下,做了个简单的例子. 目标:认证服务器认证后获取 token,客户端访问资源时带上 token 进行安全验证. 可以直接看源码. 关键依赖 <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.2

  • Spring Security认证提供程序示例详解

    1.简介 本教程将介绍如何在Spring Security中设置身份验证提供程序,与使用简单UserDetailsService的标准方案相比,提供了额外的灵活性. 2. The Authentication Provider Spring Security提供了多种执行身份验证的选项 - 所有这些都遵循简单的规范 - 身份验证请求由Authentication Provider处理,并且返回具有完整凭据的完全身份验证的对象. 标准和最常见的实现是DaoAuthenticationProvide

  • Spring Security OAuth2认证授权示例详解

    本文介绍了如何使用Spring Security OAuth2构建一个授权服务器来验证用户身份以提供access_token,并使用这个access_token来从资源服务器请求数据. 1.概述 OAuth2是一种授权方法,用于通过HTTP协议提供对受保护资源的访问.首先,OAuth2使第三方应用程序能够获得对HTTP服务的有限访问权限,然后通过资源所有者和HTTP服务之间的批准交互来让第三方应用程序代表资源所有者获取访问权限. 1.1 角色 OAuth定义了四个角色 资源所有者 - 应用程序的

  • Springboot Vue实现单点登陆功能示例详解

    目录 正文 简单上个图 先分析下登陆要做啥 怎么落实? 上代码 接口: token生成部分 刷新token 验证token 正文 登陆是系统最基础的功能之一.这么长时间了,一直在写业务,这个基础功能反而没怎么好好研究,都忘差不多了.今天没事儿就来撸一下. 以目前在接触和学习的一个开源系统为例,来分析一下登陆该怎么做.代码的话我就直接CV了. 简单上个图 (有水印.因为穷所以没开会员) 先分析下登陆要做啥 首先,搞清楚要做什么. 登陆了,系统就知道这是谁,他有什么权限,可以给他开放些什么业务功能,

  • Spring Security短信验证码实现详解

    目录 需求 实现步骤 获取短信验证码 短信验证码校验过滤器 短信验证码登录认证 配置类进行综合组装 需求 输入手机号码,点击获取按钮,服务端接受请求发送短信 用户输入验证码点击登录 手机号码必须属于系统的注册用户,并且唯一 手机号与验证码正确性及其关系必须经过校验 登录后用户具有手机号对应的用户的角色及权限 实现步骤 获取短信验证码 短信验证码校验过滤器 短信验证码登录认证过滤器 综合配置 获取短信验证码 在这一步我们需要写一个controller接收用户的获取验证码请求.注意:一定要为"/sm

  • Spring Security短信验证码实现详解

    目录 需求 实现步骤 获取短信验证码 短信验证码校验过滤器 短信验证码登录认证 配置类进行综合组装 需求 输入手机号码,点击获取按钮,服务端接受请求发送短信 用户输入验证码点击登录 手机号码必须属于系统的注册用户,并且唯一 手机号与验证码正确性及其关系必须经过校验 登录后用户具有手机号对应的用户的角色及权限 实现步骤 获取短信验证码 短信验证码校验过滤器 短信验证码登录认证过滤器 综合配置 获取短信验证码 在这一步我们需要写一个controller接收用户的获取验证码请求.注意:一定要为"/sm

  • Spring Security认证器实现过程详解

    目录 拦截请求 验证过程 返回完整的Authentication 收尾工作 结论 一些权限框架一般都包含认证器和决策器,前者处理登陆验证,后者处理访问资源的控制 Spring Security的登陆请求处理如图 下面来分析一下是怎么实现认证器的 拦截请求 首先登陆请求会被UsernamePasswordAuthenticationFilter拦截,这个过滤器看名字就知道是一个拦截用户名密码的拦截器 主要的验证是在attemptAuthentication()方法里,他会去获取在请求中的用户名密码

  • python selenium实现登录豆瓣示例详解

    使用python爬虫selenium访问豆瓣https://www.douban.com/,实现模拟登录过程. 网页界面如图所示 首先导包后,定位图中 密码登录 的element,并点击. 经分析,该标签的class_name为’account-tab-account’. from selenium import webdriver import time driver = webdriver.Chrome() driver.get('https://www.douban.com/') # 点击

  • Spring AOP事务管理的示例详解

    目录 转账案例-环境搭建 步骤1:准备数据库表 步骤2:创建项目导入jar包 步骤3:根据表创建模型类 步骤4:创建Dao接口 步骤5:创建Service接口和实现类 步骤6:添加jdbc.properties文件 步骤7:创建JdbcConfig配置类 步骤8:创建MybatisConfig配置类 步骤9:创建SpringConfig配置类 步骤10:编写测试类 事务管理 转账案例-环境搭建 步骤1:准备数据库表 之前我们在整合Mybatis的时候已经创建了这个表,可以直接使用 create

  • Spring实现泛型注入的示例详解

    目录 1.Spring泛型注入 2. 关于java泛型有四种Type GenericArrayType泛型数组类型 ParameterizedType参数化类型 TypeVariable 类型变量 WildcardType 通配符类型 1.Spring泛型注入 创建一个抽象泛型类BaseDao,有参数化类型T public abstract class BaseDao<T> { public abstract void eat(); } 每种动物有不同的行为,猫.狗 public class

随机推荐