Spring Security OAuth2 Provider 之 自定义开发

Spring OAuth2默认提供的功能难免无法满足需求,需要特殊定制,这里列举常见的几个需要特殊开发的地方。

相关文章:
[url=http://rensanning.iteye.com/blog/2384996]Spring Security OAuth2 Provider 之 最小实现[/url]
[url=http://rensanning.iteye.com/blog/2385162]Spring Security OAuth2 Provider 之 数据库存储[/url]
[url=http://rensanning.iteye.com/blog/2386309]Spring Security OAuth2 Provider 之 第三方登录简单演示[/url]
[url=http://rensanning.iteye.com/blog/2386553]Spring Security OAuth2 Provider 之 自定义开发[/url]
[url=http://rensanning.iteye.com/blog/2386766]Spring Security OAuth2 Provider 之 整合JWT[/url]

[b](1)自定义生成授权码[/b]

默认规则是:6位随机英数字。
可以通过扩展AuthorizationCodeServices来覆写已有的生成规则。通过覆写createAuthorizationCode()方法可以设置成任意的生成规则。
比如,这里实现返回32位随机英数字。
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

@Bean
protected AuthorizationCodeServices authorizationCodeServices() {
return new CustomJdbcAuthorizationCodeServices(dataSource());
}

}

public class CustomJdbcAuthorizationCodeServices extends JdbcAuthorizationCodeServices {

private RandomValueStringGenerator generator = new RandomValueStringGenerator();

public CustomJdbcAuthorizationCodeServices(DataSource dataSource) {
super(dataSource);
this.generator = new RandomValueStringGenerator(32);
}

public String createAuthorizationCode(OAuth2Authentication authentication) {
String code = this.generator.generate();
store(code, authentication);
return code;
}

}


效果如下:
[img]http://dl2.iteye.com/upload/attachment/0126/2143/21aa5ff9-b782-386d-8643-dfff179061cd.png[/img]

[b](2)自定义生成令牌[/b]

默认规则是:UUID。
Spring OAuth2提供了一个操作Token的接口TokenEnhancer,通过实现它可以任意操作accessToken和refreshToken。比如,这里实现将Token中的横线去掉。
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

@Bean
public TokenEnhancer tokenEnhancer() {
return new CustomTokenEnhancer();
}

}

public class CustomTokenEnhancer implements TokenEnhancer {

@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
if (accessToken instanceof DefaultOAuth2AccessToken) {
DefaultOAuth2AccessToken token = ((DefaultOAuth2AccessToken) accessToken);
token.setValue(getNewToken());

OAuth2RefreshToken refreshToken = token.getRefreshToken();
if (refreshToken instanceof DefaultOAuth2RefreshToken) {
token.setRefreshToken(new DefaultOAuth2RefreshToken(getNewToken()));
}

Map<String, Object> additionalInformation = new HashMap<String, Object>();
additionalInformation.put("client_id", authentication.getOAuth2Request().getClientId());
token.setAdditionalInformation(additionalInformation);

return token;
}
return accessToken;
}

private String getNewToken() {
return UUID.randomUUID().toString().replace("-", "");
}

}


效果如下:
[img]http://dl2.iteye.com/upload/attachment/0126/2145/ff21e53b-f0c5-3c2c-ac12-72df7bc9d9f2.png[/img]

[b](3)自定义授权页面[/b]

默认的定义如下:
org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint
[quote] private String userApprovalPage = "forward:/oauth/confirm_access";
private String errorPage = "forward:/oauth/error";[/quote]

org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint
[quote] @RequestMapping({"/oauth/confirm_access"})
public ModelAndView getAccessConfirmation(Map<String, Object> model, HttpServletRequest request) throws Exception {
// ...
}[/quote]

org.springframework.security.oauth2.provider.endpoint.WhitelabelErrorEndpoint
[quote] @RequestMapping({"/oauth/error"})
public ModelAndView handleError(HttpServletRequest request) {
// ...
}[/quote]

设置新的URL:
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthorizationEndpoint authorizationEndpoint;

@PostConstruct
public void init() {
authorizationEndpoint.setUserApprovalPage("forward:/oauth/my_approval_page");
authorizationEndpoint.setErrorPage("forward:/oauth/my_error_page");
}
}


页面实现:
@Controller
@SessionAttributes({ "authorizationRequest" })
public class OAuthController {

@RequestMapping({ "/oauth/my_approval_page" })
public String getAccessConfirmation(Map<String, Object> model, HttpServletRequest request) throws Exception {
@SuppressWarnings("unchecked")
Map<String, String> scopes = (Map<String, String>) (model.containsKey("scopes") ? model.get("scopes") : request.getAttribute("scopes"));
List<String> scopeList = new ArrayList<String>();
for (String scope : scopes.keySet()) {
scopeList.add(scope);
}
model.put("scopeList", scopeList);
return "oauth_approval";
}

@RequestMapping({ "/oauth/my_error_page" })
public String handleError(Map<String, Object> model, HttpServletRequest request) {
Object error = request.getAttribute("error");
String errorSummary;
if (error instanceof OAuth2Exception) {
OAuth2Exception oauthError = (OAuth2Exception) error;
errorSummary = HtmlUtils.htmlEscape(oauthError.getSummary());
} else {
errorSummary = "Unknown error";
}
model.put("errorSummary", errorSummary);
return "oauth_error";
}
}


/src/main/resources/templates/oauth_approval.html
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>approval</title>
<meta charset="utf-8"/>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-12 well">
<h3>授权页</h3>
应用名 : <span th:text="${session.authorizationRequest.clientId}">clientId</span>

<form id='confirmationForm' name='confirmationForm' th:action="@{/oauth/authorize}" method='post'>
<input name='user_oauth_approval' value='true' type='hidden' />
<input th:name="${s}" value="true" type="hidden" th:each="s : ${scopeList}" />
<input name='authorize' value='授权' type='submit' />
</form>
</div>
</div>
</div>
</body>
</html>


/src/main/resources/templates/oauth_error.html
<!DOCTYPE HTML>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<title>error</title>
<meta charset="utf-8"/>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-12 well">
<h3>错误</h3>
<p style="color:red;">出错了!不能继续授权操作!</p>
<p th:utext="${errorSummary}">errorSummary
</div>
</div>
</div>
</body>
</html>


效果如下:
[img]http://dl2.iteye.com/upload/attachment/0126/2151/a1714717-d5c2-3537-bc6f-8ddb3ee90787.png[/img]
[img]http://dl2.iteye.com/upload/attachment/0126/2149/89e4a7f9-7ca9-38cf-adee-5574b27e9c76.png[/img]

[b](4)自定义用户登录页面[/b]
这部分应该属于SpringSecurity范畴的。

[b]创建用户表[/b]
CREATE TABLE account
(
id serial NOT NULL,
user_name character varying(50),
email character varying(255),
password character varying(512),
role_string character varying(50),
CONSTRAINT account_pkey PRIMARY KEY (id)
);

INSERT INTO account(user_name, email, password, role_string)
VALUES ('user', 'user@sample.com', '123', 'ROLE_USER');


[b]配置SpringSecurity[/b]
@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
@EnableWebSecurity
static class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider);
}

@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable();

http.antMatcher("/oauth/**")
.authorizeRequests()
.antMatchers("/oauth/index").permitAll()
.antMatchers("/oauth/token").permitAll()
.antMatchers("/oauth/check_token").permitAll()
.antMatchers("/oauth/confirm_access").permitAll()
.antMatchers("/oauth/error").permitAll()
.antMatchers("/oauth/my_approval_page").permitAll()
.antMatchers("/oauth/my_error_page").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/oauth/index")
.loginProcessingUrl("/oauth/login");
}
@Autowired
private CustomAuthenticationProvider authenticationProvider;
}

@Configuration
@MapperScan("com.rensanning")
@EnableTransactionManagement(proxyTargetClass = true)
static class RepositoryConfig {
}


[b]用户登录处理部分[/b]
@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

@Autowired
private AccountService accountService;

@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {

String name = authentication.getName();
String password = authentication.getCredentials().toString();

Account account = accountService.authUser(name, password);
if (account == null) {
throw new AuthenticationCredentialsNotFoundException("Account is not found.");
}

List<GrantedAuthority> grantedAuths = AuthorityUtils.createAuthorityList(account.getRoleString());
return new UsernamePasswordAuthenticationToken(name, password, grantedAuths);
}

@Override
public boolean supports(Class<?> authentication) {
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}

@Service
public class AccountService {

@Autowired
private AccountRepository accountRepository;

public Account authUser(String userName, String password) {
Account u = accountRepository.findByUserName(userName);
if (u == null) {
return null;
}
if (!u.getPassword().equals(password)) {
return null;
}
return u;
}

}

public interface AccountRepository {
@Select("select id, user_name as userName, email, password, role_string as roleString from account where user_name=#{user_name}")
Account findByUserName(String userName);
}

@SuppressWarnings("serial")
public class Account implements Serializable {
private Integer id;
private String userName;
private String email;
private String password;
private String roleString;
// ...setter/getter
}

[img]http://dl2.iteye.com/upload/attachment/0126/2177/3dd3a570-5a62-37bd-a16e-63c565e936ff.png[/img]

完成的Client->ResoureServer->AuthServer的执行过程:
[img]http://dl2.iteye.com/upload/attachment/0126/2179/43f6a1b9-486b-3b4a-acd0-0cba13dd74d1.gif[/img]

参考:
https://stackoverflow.com/questions/29618658/spring-how-to-create-a-custom-access-and-refresh-oauth2-token
https://stackoverflow.com/questions/29345508/spring-oauth2-custom-oauth-approval-page-at-oauth-authorize
oauth2 spring-authorization-server资源拥有者模式支持手机短信,邮箱认证 1.版本 spring-security-oauth2-authorization-server 0.2.3 spring-boot 2.6.6 2.概述 目前实现的资源拥有者模式实现只支持用户名密码认证,项目有需求需要支持根据手机号,邮箱进行认证,需要改造资源拥有者模式的实现,可以让开发自定义任何和资源拥有者相关的认证方式 3.实现 ... 阅读详情

相关推荐

48-OIDC OP配置信息端点

在OAuth2AuthorizationServerMetadataEndpointFilter一文中专门提到一个对外提供授权服务器元信息的端点,遵循RFC8414相关的规范。 在OIDC 1.0中同样也有这样一个端点来提供类似的功能,相关的规范为OpenID Provider Configuration Request。...

码农小胖哥 1786

spring security OAuth2 支持

是向授权服务器注册的客户端。客户端必须先向授权服务器注册,然后才能启动授权授予流(如authorization_code或client_credentials),在客户端注册期间,客户端被分配一个唯一的客户端标识符(clientId),(可选地)一个客户端秘密(clientSecret)(取决于客户端类型),以及与其唯一客户端标识符相关联的元数据。客户机的元数据可以是面向人的显示字符串(如客户机名称),也可以是特定于协议流的项(如有效重定向uri列表)。

nmg_tl的博客 2930

6-Spring Security OAuth2配置项详解

我们在配置文件中进行了一些配置就完成了第三方OAuth2登录,这些配置项都是啥?配置文件中的gitee配置项是如何写入配置生效的呢?初学者的可能会有点懵逼。本篇将把这个疑问解决掉。 OAuth2配置项的读取 以下是Spring Boot配置文件的配置项示例: [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QN6Ba2B3-1647440314790)(.\img\application-oauth2.png)] 上图在application.yml中配置的OAuth2信息会被

码农小胖哥 5399

轻松搞定自定义Oauth2授权模式-AuthenticationProvider功能介绍

自定义oauth2授权模式开发

xunaiu34的博客 1729

地下水热耦合模拟FEFLOW建模

2.3 依据讲解内容,练习构建地下水数值模型(例二),学会各种源汇项、边界条件、时间序列、节点参数的添加及模拟结果的导出。对于真实模型,学习如何建立概念模型、数学模型,练习模型的各种参数和源汇项输入,进行溶质运移、水热模拟。3.通过多种实践案例应用,掌握实践工作中常见项目的模型搭建及特殊问题处理方法。4.1学习水热模型抽灌模式,网格剖分、边界条件、初始温度场赋值。3.3练习模型的各种参数和源汇项输入,进行水流和溶质运移模拟。2.掌握水热耦合的模拟方法及典型项目应用问题处理。2.4根据模拟结果,

weixin_55561616的博客 964

别再手动算临界转速了!用ANSYS Workbench 2023 R2快速搞定转子坎贝尔图(附完整APDL命令流)

本文详细介绍了如何利用ANSYS Workbench 2023 R2快速生成转子坎贝尔图,实现全自动临界转速分析。通过对比传统手动计算与Workbench自动化流程的效率差异,展示了其在旋转机械设计中的革命性优势,包括大幅缩短分析周期、提升精度至98.7%。文章还提供了完整的APDL命令流和实战案例,帮助工程师快速掌握这一高效工具。

weixin_42699679的博客 472

oauth2自定义granter与provider实现自定义身份认证

oauth接收到了你传入的grant_type,并把你的请求转发到了你自己的Granter,但谁来进行真正的用户信息合法性校验呢?这段代码比较简单,说白了,当用户进行身份校验时,如果传入的grant_type为group_token_authentication,那么则自动进入这段逻辑创建GroupCompanyAuthenticationToken对象的实例,并将request接收到的参数传入。同时,还提供了认证模式的扩展机制,以便于我们在遇到特殊情况时根据自己的需求来完成身份验证。

weixin_45738731的博客 1387

告别手动标注!PDMS NakiToolkit插件安装与初体验:以Pipeline工具为例

本文详细介绍了PDMS NakiToolkit插件的安装与使用,特别是其Pipeline工具如何通过自动化标注和材料统计功能大幅提升三维工厂设计效率。从环境准备到实战演示,帮助工程师告别繁琐的手动标注工作,实现项目交付周期的大幅缩短。

weixin_30047059的博客 351

SpringSecurity Oauth2 - 04 自定义AuthProvider实现认证登录

}注意:/api/v1/login 请求资源时受保护的资源,因此需要在资源服务器中放行该请求http . authorizeRequests() // 放行的请求 . antMatchers("/api/v1/login") . permitAll() // 其他请求必须认证才能访问 . anyRequest() . authenticated() . and() . csrf() . disable();} }

你今天真好看呀 2046

8、干式变压器

干式变压器的发展,是人类不断挑战材料科学和热物理极限的过程,每一次技术突破,都是在。温度升高,ε_r反而下降(因为分子活动性增强,极化响应变慢)。:固体导热的热阻比液体对流大一个数量级,这是无法逾越的物理规律。Nomex在高温下不是逐渐分解,而是保持性能直到一个临界点。如果 T_a = 40°C,则 T_c = 146.7°C。干式变压器(固体介质分隔):热场、电场、流场(空气)形成三维氢键网络,即使在高温下也能保持机械强度。:不是在现有技术上修修补补,而是寻找新的。仍在H级绝缘允许范围内(≤180°C)

renpeng2692873032的博客 228

SolidWorks 小车底盘 装配体

通过制作小车底盘了解solidworks装配体的部分知识

及时总结 2229

Spring Security OAuth 2 开发指南

Spring Security OAuth 2 开发指南 本文档翻译自http://projects.spring.io/spring-security-oauth/docs/oauth2.html 简介 这是为支持 OAuth 2.0 的用户指南,OAuth1.0很多都不一样,请访问 O...

chongjiangfang8251的博客 417

手机相机Tuning专项调优(一):基础流程与图像主观评价标准建立实战解析

本篇为手机相机系统“Tuning专项调优”系列的开篇,深入剖析了当前手机相机Tuning的基本流程与图像主观评价标准的构建方法。结合实际工程经验与最新业界案例,详细介绍ISP调优和3A控制中涉及的主观评价标准,如锐度、色彩饱和度、噪声感知等,并提出一套可工程化落地的标准制定与评测实践体系,帮助工程师有效提升图像品质。

努力分享一些人工智能、计算机视觉、影像等相关的知识干货! 1933

【Spring Security OAuth2】- spring security - 短信登录开发

自定义认证逻辑的配置大致步骤:入口配置 应用方使用该配置提供处理过滤器 ProcessingFilter 并限制该过滤器支持拦截的url提供AuthenticationProvider 进行认证的处理支持把ProviderManager 赋值给 ProcessingFilter把AuthenticationProvider注册到AuthenticationManager中去(这里完成ProcessingFilter调用管理器查找Provider,完成认证这个过程)

smart_an的专栏 1154

2023华为OD面试手撕真题【最长公共前缀】

2023华为OD面试手撕真题【最长公共前缀】

MISAYAONE的博客 5242

uniapp [安卓苹果App端] - 实现微信支付功能+拉起微信付款支付后返回本app页面,详解uniApp如何唤起本机微信app并跳转到支付页面全流程及示例源码(uniapp实现微信支付,可打包)

uni-app项目在APP端使用微信支付功能,uniapp前端实现微信支付,uniapp开发安卓App对接微信支付,uniapp苹果ios唤起微信支付,uniapp调用微信支付uniapp开发app-调用微信支付,uniapp开发安卓苹果app如何接入微信支付,前后端应该怎么做,UniApp中实现微信支付功能,支付报错,调起失败没响应,uniapp苹果微信支付唤起实现,app唤起微信支付,拉起微信支付,uniapp中唤醒微信进行支付并返回app,uniApp调起微信支付失败报错,全网最详细的uniapp微信

🏆 前端领域优质创作者 1万+

springCloud +OAuth2 单点登录接入

springCloud +OAuth2 单点登录接入

xiaogg3678的专栏 216

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

告别账号密码:用若依Security实现微信小程序一键登录的完整流程与原理剖析

本文详细解析了如何利用若依Security框架实现微信小程序一键登录,提升用户体验和转化率。通过混合认证体系架构设计、自定义认证令牌实现及安全配置调整,开发者可以构建与现有账号体系无缝融合的登录方案,同时确保安全性和性能优化。

weixin_42522320的博客 301

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

Spring Security实现OAuth2协议及实战

OAuth2是目前最流行的授权协议,用来授权第三方应用,获取用户数据。举个例子:快递员想要进入小区,有3种方式。1是业主远程开门,2是业主告诉门禁密码,3是使用令牌(Oauth2)。如图:令牌和密码的区别:令牌相当于火车票,密码相当于是钥匙。令牌是短期的,自动失效。密码是长期有效。令牌是可以撤销的,撤销立即生效。密码一般不允许他们撤销。令牌有权限范围,如车票座位为10车A15座。密码一般是完整权限。第三方登录演示(网易云客户端利用QQ扫码登录)

qq_43372633的博客 3005

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Spring Security Oauth2 扩展登录方式

第一步:新建filter,这里以手机验证码登录为例子 /** * @Author: 朱维 * @Date 16:52 2019/11/27 * /phoneLogin?telephone=13000000000&smsCode=1000 */ public class PhoneLoginAuthenticationFilter extends AbstractAuthenti...

zhuwei_clark的博客 3045

【Spring Security + OAuth2】OAuth2

Auth”表示“授权”Authorization"O"是Open的简称,表示“开放”连在一起就表示“开发授权”,OAuth2是一种开放授权协议在实际流程中,颁发Token前先要征询用户同意。

weixin_43676950的博客 2406

Spring Security OAuth2 开发指南中文版

转载:https://www.ktanx.com/blog/p/5008 介绍 这是 OAuth 2.0 的用户指南。OAuth 1.0 与之大不相同,若有需求,请阅读 1.0 的用户指南。 本用户指南分为两个部分,一部分针对的是 OAuth 2.0 的提供方[译者注:通常指服务提供方],另一部分则是针对 OAuth 2.0 客户端。对于提供方和客户端双方来说,最好的示例代码是集成测试和示例...

xqhys的博客 2万+

Spring OAuth2.0客户端源码解析

介绍OAuth2.0授权码模式下Spring Boot OAuth2客户端的源码运行流程

onePlus5T的博客 2237

spring cloud OAuth2

1.spring cloud oauth的原理 2.spring cloud oauth的配置 3.spring cloud oauth的实例 4.总结

a18792721831的博客 4571

【Spring Security OAuth2】- spring security - 认证流程源码级详解

作者简介:大家好,我是哥,前中兴通讯、美团架构师,现某互联网公司联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬学习必须往深处挖,挖的越深,基础越扎实!

smart_an的专栏 1199
上一篇: Spring Security OAuth2 Provider 之 第三方登录简单演示
下一篇: Spring Security OAuth2 Provider 之 整合JWT
wayne_ren
博客等级 码龄21年 60粉丝 300原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值