一、Oauth2协议:

第三方登录,即忘记本站密码,但是登录界面中提供了一些第三方登录,例如微信、支付宝、QQ、等等,通过第三方授权实现登录

第三方认证技术主要解决的时认证标准,各个平台的登录要遵循统一的接口协议

所以这里采用的方案是Oauth2

资料参考:

https://www.jianshu.com/p/84a4b4a1e833

二、Spring-Security + Oauth2 环境搭建

创建一个空的SpringBoot项目:

删除不必要的文件

导入POM依赖坐标:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>cn.zeal4j</groupId>
<artifactId>so2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>so2</name>
<description>Spring-Security + Oauth2 project for Spring Boot</description> <properties>
<java.version>1.8</java.version>
<spring-cloud.version>Greenwich.SR2</spring-cloud.version>
</properties> <dependencies> <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
<!--<version>2.2.4.RELEASE</version>-->
</dependency> <dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-security</artifactId>
<!--<version>2.2.4.RELEASE</version>-->
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency> <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies> <dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version><!--<version>Greenwich.SR2</version>-->
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build> </project>

用户实体类:

package cn.zeal4j.domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails; import java.util.Collection; /**
* @author Administrator
* @file Spring-Security + Oauth2
* @create 2020 09 29 11:37
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User implements UserDetails {
private String username;
private String password;
private Collection<GrantedAuthority>
authorities; @Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
} @Override
public String getPassword() {
return null;
} @Override
public String getUsername() {
return null;
} @Override
public boolean isAccountNonExpired() {
return false;
} @Override
public boolean isAccountNonLocked() {
return false;
} @Override
public boolean isCredentialsNonExpired() {
return false;
} @Override
public boolean isEnabled() {
return false;
}
}

Security安全配置:

package cn.zeal4j.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder; /**
* @author Administrator
* @file Spring-Security + Oauth2
* @create 2020 09 29 11:35
*/
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Bean
public PasswordEncoder getPasswordEncoder() {
return new BCryptPasswordEncoder();
} @Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
// csrf
httpSecurity.csrf().disable(); // 登录,退出,授权放行
httpSecurity.authorizeRequests().antMatchers("/login/**","/logout/**","/oauth/**/").permitAll(); // 允许表单登录
httpSecurity.formLogin().permitAll(); // 其余请求权限拦截
httpSecurity.authorizeRequests().anyRequest().authenticated();
}
}

授权服务配置:

package cn.zeal4j.configuration;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer; /**
* @author Administrator
* @file Spring-Security + Oauth2
* @create 2020 09 29 11:48
* @description 授权服务器配置
*/
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter { @Autowired
private PasswordEncoder passwordEncoder; @Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.
inMemory().
withClient("admin").
secret(passwordEncoder.encode("112233")).
accessTokenValiditySeconds(3600). // 令牌有效时间 一小时
redirectUris("http://www.baidu.com"). // 授权成功的跳转
scopes("all"). // 所有范围
authorizedGrantTypes("authorization_code"); // 授权类型:授权码模式
}
}

资源服务配置:

package cn.zeal4j.configuration;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter; /**
* @author Administrator
* @file Spring-Security + Oauth2
* @create 2020 09 29 11:57
*/ @Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { @Override
public void configure(HttpSecurity httpSecurity) throws Exception { httpSecurity.authorizeRequests().
anyRequest().authenticated(). // 默认任何请求都需要授权
and().
requestMatchers().antMatchers("/user/**"); // 资源匹配规则
}
}

登录逻辑:

package cn.zeal4j.service.impl;

import cn.zeal4j.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder; /**
* @author Administrator
* @file Spring-Security + Oauth2
* @create 2020 09 29 11:35
*/
@Service
public class CustomUserDetailsServiceImpl implements UserDetailsService { @Autowired
private PasswordEncoder passwordEncoder; @Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
String encode = passwordEncoder.encode("123456");
return new User("admin", encode, AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
}
}

User资源控制器:

package cn.zeal4j.controller;

import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody; /**
* @author Administrator
* @file Spring-Security + Oauth2
* @create 2020 09 29 12:01
*/
@Controller
@RequestMapping("user")
public class UserController { /**
* 获取当前用户
* @param authentication
* @return user/getCurrentUser
*/
@RequestMapping("/getCurrentUser")
@ResponseBody
public Object getCurrentUser(Authentication authentication) {
return authentication.getPrincipal();
} }

启动访问发现:

二、授权码模式实现:

发现生成的UserDetails实例默认设置的都是False,SpringSecurity一经权限判断,直接触发拦截

所以默认这里都要改成TRUE放行通过

    @Override
public String getPassword() {
return password;
} @Override
public String getUsername() {
return username;
} @Override
public boolean isAccountNonExpired() {
return true;
} @Override
public boolean isAccountNonLocked() {
return true;
} @Override
public boolean isCredentialsNonExpired() {
return true;
} @Override
public boolean isEnabled() {
return true;
}

再次测试Oauth2地址:

http://localhost:8080/oauth/authorize?response_type=code&client_id=admin&redirect_uri=http://www.baidu.com&scope=all

点击选择Approve允许,点击Authorize进行授权

https://www.baidu.com/?code=G6ocWn

这个code就是我们的授权码

现在使用Postman进行测试:

1、先选择认证账号信息输入:

2、然后输入请求参数:

grant_type    authorization_code
code 你得到的授权码
cient_id admin
redirect_uri http://www.baidu.com
scope all

请求成功则会返回这个消息JSON

{
"access_token": "4c562cc7-07c4-47b6-9a5b-537c4f4079cd",
"token_type": "bearer",
"expires_in": 43199,
"scope": "all"
}

得到了许可Token

接着用Token访问资源获取接口:

http://localhost:8080/user/getCurrentUser

得到我们返回的数据:

{
"username": "admin",
"password": "$2a$10$tBlHK4KbNFsE7F7usl6AsODWWBkF4oS8Ak4qkaNbEFAsKykvXgH9i",
"authorities": [
{
"authority": "admin"
}
],
"enabled": true,
"accountNonLocked": true,
"credentialsNonExpired": true,
"accountNonExpired": true
}

如果令牌是错误的

{
"error": "invalid_token",
"error_description": "Invalid access token: 2287c3ab-3dc5-475e-97eb-bdffb2a78b8A"
}

三、密码模式授权实现:

package cn.zeal4j.configuration;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer; /**
* @author Administrator
* @file Spring-Security + Oauth2
* @create 2020 09 29 11:48
* @description 授权服务器配置
*/
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter { @Autowired
private PasswordEncoder passwordEncoder; @Autowired
private AuthenticationManager authenticationManager;
@Qualifier("customUserDetailsServiceImpl")
@Autowired
private UserDetailsService userDetailsService; /**
* 使用密码模式需要的配置方法
* @param endpoints
* @throws Exception
*/
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws
Exception {
endpoints.
authenticationManager(authenticationManager).
userDetailsService(userDetailsService);
}

@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.
inMemory().
withClient("admin").
secret(passwordEncoder.encode("112233")).
// accessTokenValiditySeconds(3600). // 令牌有效时间 一小时
redirectUris("http://www.baidu.com"). // 授权成功的跳转
scopes("all"). // 所有范围
// authorizedGrantTypes("authorization_code"); // 授权类型:授权码模式
authorizedGrantTypes("password"); // 授权类型:密码模式

}
}

授权管理器Bean的注入:

package cn.zeal4j.configuration;

import org.omg.CORBA.PUBLIC_MEMBER;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder; /**
* @author Administrator
* @file Spring-Security + Oauth2
* @create 2020 09 29 11:35
*/
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Bean
public PasswordEncoder getPasswordEncoder() {
return new BCryptPasswordEncoder();
} @Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super
.authenticationManagerBean();
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.
csrf().
disable().
authorizeRequests().
antMatchers("/login/**","/logout/**","/oauth/**/").permitAll().
anyRequest().authenticated().
and().
formLogin().permitAll(); // // csrf
// httpSecurity.csrf().disable();
//
// // 登录,退出,授权放行
// httpSecurity.authorizeRequests().antMatchers("/login/**","/logout/**","/oauth/**/").permitAll();
//
// // 允许表单登录
// httpSecurity.formLogin().permitAll();
//
// // 其余请求权限拦截
// httpSecurity.authorizeRequests().anyRequest().authenticated();
}
}

Postman请求的地址和前面的密码不变,但是更改授权参数

{
"access_token": "8e51bdc3-50cd-42bd-b41c-28f06e5eca1f",
"token_type": "bearer",
"expires_in": 43199,
"scope": "all"
}

用密码模式的令牌获取用户主体,也能拿到用户主体的信息:

【Spring-Security】Re10 Oauth2协议 P1 授权码模式 & 密码模式的更多相关文章

  1. Spring Security实现OAuth2.0授权服务 - 基础版

    一.OAuth2.0协议 1.OAuth2.0概述 OAuth2.0是一个关于授权的开放网络协议. 该协议在第三方应用与服务提供平台之间设置了一个授权层.第三方应用需要服务资源时,并不是直接使用用户帐 ...

  2. Spring Cloud2.0之Oauth2环境搭建(授权码模式和密码授权模式)

    oauth2 server 微服务授权中心,    github源码  https://github.com/spring-cloud/spring-cloud-security 对微服务接口做一些权 ...

  3. Spring Security实现OAuth2.0授权服务 - 进阶版

    <Spring Security实现OAuth2.0授权服务 - 基础版>介绍了如何使用Spring Security实现OAuth2.0授权和资源保护,但是使用的都是Spring Sec ...

  4. Spring Security中实现微信网页授权

    微信公众号提供了微信支付.微信优惠券.微信H5红包.微信红包封面等等促销工具来帮助我们的应用拉新保活.但是这些福利要想正确地发放到用户的手里就必须拿到用户特定的(微信应用)微信标识openid甚至是用 ...

  5. Spring Security 与 OAuth2 介绍

    个人 OAuth2 全部文章 Spring Security 与 OAuth2(介绍):https://www.jianshu.com/p/68f22f9a00ee Spring Security 与 ...

  6. Spring Security 与 OAuth2(介绍)

    https://www.jianshu.com/p/68f22f9a00ee Spring Security 与 OAuth2(介绍) 林塬 2018.01.23 11:14* 字数 3097 阅读 ...

  7. Spring Security基于Oauth2的SSO单点登录怎样做?一个注解搞定

    一.说明 单点登录顾名思义就是在多个应用系统中,只需要登录一次,就可以访问其他相互信任的应用系统,免除多次登录的烦恼.本文主要介绍 同域 和 跨域 两种不同场景单点登录的实现原理,并使用 Spring ...

  8. spring security之 默认登录页源码跟踪

    spring security之 默认登录页源码跟踪 ​ 2021年的最后2个月,立个flag,要把Spring Security和Spring Security OAuth2的应用及主流程源码研究透 ...

  9. Oauth2.0认证---授权码模式

    目录: 1.功能描述 2.客户端的授权模式 3.授权模式认证流程 4.代码实现 1.功能描述 OAuth在"客户端"与"服务提供商"之间,设置了一个授权层(au ...

  10. spring boot:spring security实现oauth2+jwt管理认证授权及oauth2返回结果格式化(spring boot 2.3.3)

    一,为什么oauth2要整合jwt? 1,OAuth2的token技术有一个最大的问题是不携带用户信息,所以资源服务器不能进行本地验证, 以致每次对于资源的访问,资源服务器都需要向认证服务器的toke ...

随机推荐

  1. 从零开始的常用MySQL语句练习大全

    先说一些废话 很多时候深入学习固然很重要,但是想要写下一篇给新手都能看得懂看的很香,并且老鸟可以查漏补缺的的练习博客,还是挺有难度, 所以今天尝试写一些关于MySQL的语句练习大全,供想要从零开始练习 ...

  2. JS注释 JS变量

    <!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8 ...

  3. zkq 数学听课笔记

    线性代数 域 \(F\),OI 中常用的域是 \(\Z_{p^c}\). \(n\) 维向量 \(\vec x \in F^n\),其中 \(x_i \in F\),注意向量是列向量. \(F^n\) ...

  4. 使用 OpenTelemetry 构建可观测性 02 - 埋点

    这是讲解 OpenTelemetry 系列博客的第二篇.在上一篇博客中,我们介绍了 OpenTelemetry 是什么以及由什么组成.现在我们将讨论如何使用 OTel 准确收集遥测数据和链路追踪数据. ...

  5. ELK收集主流应用日志

    1.收集nginx日志 学习背景:access.log,error.log目前日志混杂在一个es索引下. 改进filebeat配置 https://www.elastic.co/guide/en/be ...

  6. 神奇的JavaScript弱等价类型转换

    JavaScript语言特性 - 类型转换 JavaScript这门语言的类型系统从来没有它表面看起来的那样和善,虽然比起Java.C#等一众强类型语言,它的弱类型使用起来似乎是如此便利,但正因为它极 ...

  7. Excel表格MID函数使用-截图单元格字符长度

    Excel表格MID函数使用-截图单元格字符长度 =MID(B2,1,6) //代表的是从B2单元格,从第1个字符开始,截图6个字符长度.然后双击该单元格,整个列都会截取

  8. Ansible的常用模块

    目录 ansible常用模块 1. file模块 1.1 file模块的选项 1.2 file模块的使用 1.2.1 使用file模块在远程主机创建文件 1.2.2 创建目录 1.2.3 删除文件/目 ...

  9. spring与设计模式之四适配器模式

    一.定义 适配器模式-或者称为转接口模式,变压器模式.通过适配,可以让原来提供特定功能的对象完成另外一个标准的功能. 所以,所谓的适配应该可以这样称呼:让某些类/接口适配/转换某个标准/功能. 适配器 ...

  10. MySQL日志(redo log、binlog)刷盘策略

    通过上篇文章,我们知道MySQL是采用两段提交策略来保证事务的原子性的,redo log刷盘的时机是在事务提交的commit阶段采取刷盘的,在此之前,redo log都存在于redo log buff ...