一、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. zkq 数学听课笔记

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

  2. CRP关键渲染路径笔记

    关键渲染路径CRP笔记 关键渲染路径(Critical Render Process)是浏览器将HTML.CSS和JavaScript代码转换为屏幕上像素的步骤序列,它包含了DOM(Document ...

  3. java8 Lambda及Stream学习笔记

    Lambda表达式Lambda 表达式可以替代只有一个抽象函数的接口实现. Lambda表达式同时还提升了对集合.框架的迭代.遍历.过滤数据的操作. Lambda表达式使用场景任何有函数式接口的地方 ...

  4. 2019银川区域赛BDFGHIKN题解

    B.So Easy 题目大意:给你一个正方形矩阵,初始都是0,题目对这个矩阵做了许多次操作,每次操作把行+1或列+1.其中有一个元素被隐藏了,你需要找出这个被隐藏的元素并判断它在操作之后应该是多少. ...

  5. Winform程序获取不到windows系统下本机的配置信息(解决)

    无法获取到本地的mac地址的原因: 本地网络问题 相关服务被禁用 wmi配置错误或者失败. 本文着力于第三种问题的解决:可以参考 无法获取本地mac,如果是wmi服务没有打开的问题.可以使用运行wmi ...

  6. arm 移植 lighttpd + CGI 配置

    --- title: arm 移植 lighttpd + CGI 配置 EntryName: porting-lighttpd-on-arm-and-make-cgi-config date: 202 ...

  7. Nginx配置以及热升级

    目录 Nginx详解 1. Nginx关键特性 2. Nginx配置 2.1 event 2.2 http 2.2.1 log_format 2.2.2 sendfile 2.2.3 tcp_nopu ...

  8. 3.5 Y84-64的流水线实现

    我们终于准备好要开始本章的主要任务--设计一个流水线化的Y86-64处理器.首先,对顺序的SEQ处理器做一点小的改动,将PC的计算挪到取指阶段.然后,在各个阶段之间加上流水线寄存器.到这个时候,我们的 ...

  9. EXPLAIN sql优化方法

    select A . id , A . title , B . title from jos_content   A left join jos_categories B on A . catid = ...

  10. redis雪崩

    每个key(即数据)如果设置了失效时间的话,如果大量key同时过期的时候,或者说因为某种原因redis中的数据突然大批量丢失,这些key又大量地去请求这些key时,因为redis里面没有这些数据,就会 ...