一、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. react 数据请求分层

    封装一个接口请求类 数据模型 请求uri配置设置 数据统一存储于redux中,在本项目中创建一个store目录,此目录中就是redux仓库源 定义仓库入口 reducer methods方法 acti ...

  2. LeetCode 699. Falling Squares 掉落的方块 (Java)

    题目: On an infinite number line (x-axis), we drop given squares in the order they are given. The i-th ...

  3. kettle从入门到精通 第三十五课 kettle 变量

    1.设置变量 a.可以通过转换中的"设置变量"步骤进行设置. b.手动通过kettle.properties文件或通过"编辑"菜单中的"设置环境变量& ...

  4. edge浏览器禁用搜索工具栏或七七八八的东西

    edge浏览器禁用搜索工具栏或七七八八的东西 在浏览器地址里输入: edge://flags/#edge-show-feature-recommendations 把"Show featur ...

  5. 小米 红米 Redmi MIUI 5G开关

    小米 红米 Redmi MIUI 5G开关 1.打开手机拨号界面输入 *#*#54638#*#* 之后拨号界面底部会显示display 5G network menu (显示5G网络菜单) 注意:先是 ...

  6. 直播预告|把握转型浪潮下的机会,甄知科技教你保姆级IT服务管理

    近年来,5G.云计算.大数据.物联网.区块链.人工智能等新兴技术不断在企业中协同发展应用,推动着企业的数字化程度逐步加深.自新冠疫情发生以来,企业的远程服务.服务自助等服务需求激增,企业数字化转型需求 ...

  7. 微信支付普通商户与AppID账号关联管理-授权

    微信支付普通商户与AppID账号关联管理 二.名词解释 名词 释义 微信支付普通商户 公司企业.政府机关.事业单位.社会组织.个体工商户.个人卖家.小微商户.(微信支付商户接入指引) AppID 已通 ...

  8. Spring Boot 使用 拦截器 实现 token 验证

    Spring Boot 使用 拦截器 实现 token 验证 整体思路:1.写一个工具类封装生成.校验和解析 token 的方法:2.在注册和登录时生成 token ,生成的 token 存入 red ...

  9. Diffusers实战

    Smiling & Weeping ---- 一生拥有自由和爱,是我全部的野心 1. 环境准备 %pip install diffusers from huggingface_hub impo ...

  10. BST-splay板子 - 维护一个分裂和合并的序列

    splay 均摊复杂度 \(O(\log n)\) 证明: https://www.cnblogs.com/Mr-Spade/p/9715203.html 我这个 splay 有两个哨兵节点,分别是1 ...