Spring Security OAuth2 Provider 之 自定义开发

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

相关文章: 
Spring Security OAuth2 Provider 之 最小实现 
Spring Security OAuth2 Provider 之 数据库存储 
Spring Security OAuth2 Provider 之 第三方登录简单演示 
Spring Security OAuth2 Provider 之 自定义开发 
Spring Security OAuth2 Provider 之 整合JWT

(1)自定义生成授权码

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

Java代码  

  1. @Configuration
  2. @EnableAuthorizationServer
  3. public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
  4. @Bean
  5. protected AuthorizationCodeServices authorizationCodeServices() {
  6. return new CustomJdbcAuthorizationCodeServices(dataSource());
  7. }
  8. }
  9. public class CustomJdbcAuthorizationCodeServices extends JdbcAuthorizationCodeServices {
  10. private RandomValueStringGenerator generator = new RandomValueStringGenerator();
  11. public CustomJdbcAuthorizationCodeServices(DataSource dataSource) {
  12. super(dataSource);
  13. this.generator = new RandomValueStringGenerator(32);
  14. }
  15. public String createAuthorizationCode(OAuth2Authentication authentication) {
  16. String code = this.generator.generate();
  17. store(code, authentication);
  18. return code;
  19. }
  20. }

效果如下: 

(2)自定义生成令牌

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

Java代码  

  1. @Configuration
  2. @EnableAuthorizationServer
  3. public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
  4. @Bean
  5. public TokenEnhancer tokenEnhancer() {
  6. return new CustomTokenEnhancer();
  7. }
  8. }

Java代码  

  1. public class CustomTokenEnhancer implements TokenEnhancer {
  2. @Override
  3. public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
  4. if (accessToken instanceof DefaultOAuth2AccessToken) {
  5. DefaultOAuth2AccessToken token = ((DefaultOAuth2AccessToken) accessToken);
  6. token.setValue(getNewToken());
  7. OAuth2RefreshToken refreshToken = token.getRefreshToken();
  8. if (refreshToken instanceof DefaultOAuth2RefreshToken) {
  9. token.setRefreshToken(new DefaultOAuth2RefreshToken(getNewToken()));
  10. }
  11. Map<String, Object> additionalInformation = new HashMap<String, Object>();
  12. additionalInformation.put("client_id", authentication.getOAuth2Request().getClientId());
  13. token.setAdditionalInformation(additionalInformation);
  14. return token;
  15. }
  16. return accessToken;
  17. }
  18. private String getNewToken() {
  19. return UUID.randomUUID().toString().replace("-", "");
  20. }
  21. }

效果如下: 

(3)自定义授权页面

默认的定义如下: 
org.springframework.security.oauth2.provider.endpoint.AuthorizationEndpoint

引用

private String userApprovalPage = "forward:/oauth/confirm_access"; 
  private String errorPage = "forward:/oauth/error";

org.springframework.security.oauth2.provider.endpoint.WhitelabelApprovalEndpoint

引用

@RequestMapping({"/oauth/confirm_access"}) 
  public ModelAndView getAccessConfirmation(Map<String, Object> model, HttpServletRequest request) throws Exception { 
    // ... 
  }

org.springframework.security.oauth2.provider.endpoint.WhitelabelErrorEndpoint

引用

@RequestMapping({"/oauth/error"}) 
  public ModelAndView handleError(HttpServletRequest request) { 
    // ... 
  }

设置新的URL:

Java代码  

  1. @Configuration
  2. @EnableAuthorizationServer
  3. public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
  4. @Autowired
  5. private AuthorizationEndpoint authorizationEndpoint;
  6. @PostConstruct
  7. public void init() {
  8. authorizationEndpoint.setUserApprovalPage("forward:/oauth/my_approval_page");
  9. authorizationEndpoint.setErrorPage("forward:/oauth/my_error_page");
  10. }
  11. }

页面实现:

Java代码  

  1. @Controller
  2. @SessionAttributes({ "authorizationRequest" })
  3. public class OAuthController {
  4. @RequestMapping({ "/oauth/my_approval_page" })
  5. public String getAccessConfirmation(Map<String, Object> model, HttpServletRequest request) throws Exception {
  6. @SuppressWarnings("unchecked")
  7. Map<String, String> scopes = (Map<String, String>) (model.containsKey("scopes") ? model.get("scopes") : request.getAttribute("scopes"));
  8. List<String> scopeList = new ArrayList<String>();
  9. for (String scope : scopes.keySet()) {
  10. scopeList.add(scope);
  11. }
  12. model.put("scopeList", scopeList);
  13. return "oauth_approval";
  14. }
  15. @RequestMapping({ "/oauth/my_error_page" })
  16. public String handleError(Map<String, Object> model, HttpServletRequest request) {
  17. Object error = request.getAttribute("error");
  18. String errorSummary;
  19. if (error instanceof OAuth2Exception) {
  20. OAuth2Exception oauthError = (OAuth2Exception) error;
  21. errorSummary = HtmlUtils.htmlEscape(oauthError.getSummary());
  22. } else {
  23. errorSummary = "Unknown error";
  24. }
  25. model.put("errorSummary", errorSummary);
  26. return "oauth_error";
  27. }
  28. }

/src/main/resources/templates/oauth_approval.html

Html代码  

  1. <!DOCTYPE HTML>
  2. <html xmlns="http://www.w3.org/1999/xhtml"
  3. xmlns:th="http://www.thymeleaf.org">
  4. <head>
  5. <title>approval</title>
  6. <meta charset="utf-8"/>
  7. </head>
  8. <body>
  9. <div class="container">
  10. <div class="row">
  11. <div class="col-md-12 well">
  12. <h3>授权页</h3>
  13. 应用名 : <span th:text="${session.authorizationRequest.clientId}">clientId</span>
  14. <form id=‘confirmationForm‘ name=‘confirmationForm‘ th:action="@{/oauth/authorize}" method=‘post‘>
  15. <input name=‘user_oauth_approval‘ value=‘true‘ type=‘hidden‘ />
  16. <input th:name="${s}" value="true" type="hidden" th:each="s : ${scopeList}" />
  17. <input name=‘authorize‘ value=‘授权‘ type=‘submit‘ />
  18. </form>
  19. </div>
  20. </div>
  21. </div>
  22. </body>
  23. </html>

/src/main/resources/templates/oauth_error.html

Html代码  

  1. <!DOCTYPE HTML>
  2. <html xmlns="http://www.w3.org/1999/xhtml"
  3. xmlns:th="http://www.thymeleaf.org">
  4. <head>
  5. <title>error</title>
  6. <meta charset="utf-8"/>
  7. </head>
  8. <body>
  9. <div class="container">
  10. <div class="row">
  11. <div class="col-md-12 well">
  12. <h3>错误</h3>
  13. <p style="color:red;">出错了!不能继续授权操作!</p>
  14. <p th:utext="${errorSummary}">errorSummary
  15. </div>
  16. </div>
  17. </div>
  18. </body>
  19. </html>

效果如下: 
 

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

创建用户表

Sql代码  

  1. CREATE TABLE account
  2. (
  3. id serial NOT NULL,
  4. user_name character varying(50),
  5. email character varying(255),
  6. password character varying(512),
  7. role_string character varying(50),
  8. CONSTRAINT account_pkey PRIMARY KEY (id)
  9. );
  10. INSERT INTO account(user_name, email, password, role_string)
  11. VALUES (‘user‘, ‘[email protected]‘, ‘123‘, ‘ROLE_USER‘);

配置SpringSecurity

Java代码  

  1. @Configuration
  2. @Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
  3. @EnableWebSecurity
  4. static class SecurityConfig extends WebSecurityConfigurerAdapter {
  5. @Override
  6. protected void configure(AuthenticationManagerBuilder auth) throws Exception {
  7. auth.authenticationProvider(authenticationProvider);
  8. }
  9. @Override
  10. protected void configure(HttpSecurity http) throws Exception {
  11. http.csrf().disable();
  12. http.antMatcher("/oauth/**")
  13. .authorizeRequests()
  14. .antMatchers("/oauth/index").permitAll()
  15. .antMatchers("/oauth/token").permitAll()
  16. .antMatchers("/oauth/check_token").permitAll()
  17. .antMatchers("/oauth/confirm_access").permitAll()
  18. .antMatchers("/oauth/error").permitAll()
  19. .antMatchers("/oauth/my_approval_page").permitAll()
  20. .antMatchers("/oauth/my_error_page").permitAll()
  21. .anyRequest().authenticated()
  22. .and()
  23. .formLogin()
  24. .loginPage("/oauth/index")
  25. .loginProcessingUrl("/oauth/login");
  26. }
  27. @Autowired
  28. private CustomAuthenticationProvider authenticationProvider;
  29. }

Java代码  

  1. @Configuration
  2. @MapperScan("com.rensanning")
  3. @EnableTransactionManagement(proxyTargetClass = true)
  4. static class RepositoryConfig {
  5. }

用户登录处理部分

Java代码  

  1. @Component
  2. public class CustomAuthenticationProvider implements AuthenticationProvider {
  3. @Autowired
  4. private AccountService accountService;
  5. @Override
  6. public Authentication authenticate(Authentication authentication) throws AuthenticationException {
  7. String name = authentication.getName();
  8. String password = authentication.getCredentials().toString();
  9. Account account = accountService.authUser(name, password);
  10. if (account == null) {
  11. throw new AuthenticationCredentialsNotFoundException("Account is not found.");
  12. }
  13. List<GrantedAuthority> grantedAuths = AuthorityUtils.createAuthorityList(account.getRoleString());
  14. return new UsernamePasswordAuthenticationToken(name, password, grantedAuths);
  15. }
  16. @Override
  17. public boolean supports(Class<?> authentication) {
  18. return authentication.equals(UsernamePasswordAuthenticationToken.class);
  19. }
  20. }

Java代码  

  1. @Service
  2. public class AccountService {
  3. @Autowired
  4. private AccountRepository accountRepository;
  5. public Account authUser(String userName, String password) {
  6. Account u = accountRepository.findByUserName(userName);
  7. if (u == null) {
  8. return null;
  9. }
  10. if (!u.getPassword().equals(password)) {
  11. return null;
  12. }
  13. return u;
  14. }
  15. }

Java代码  

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

Java代码  

  1. @SuppressWarnings("serial")
  2. public class Account implements Serializable {
  3. private Integer id;
  4. private String userName;
  5. private String email;
  6. private String password;
  7. private String roleString;
  8. // ...setter/getter
  9. }

完成的Client->ResoureServer->AuthServer的执行过程: 

参考: 
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

1 

1 

分享到:  

Spring Security OAuth2 Provider 之 整合 ... | Spring Security OAuth2 Provider 之 第三 ...

评论

3 楼 IT小新 2017-10-27

求该例子得示例代码呗,谢谢了

2 楼 xu_yuan 2017-10-24

LS少写了thymeleaf的配置,如果不加的话,是不能识别thymeleaf语法的html文件的。会导致controller虽然返回了oauth_approval,但是却报错error 找不到mapping

配置自定义授权页
POM.xml 需要加入以下配置

Xml代码  

  1. <!---模板引擎:网页路径渲染-->
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-thymeleaf</artifactId>
  5. </dependency>

application.yml 需要加入以下配置

Yml代码  

  1. spring:
  2. thymeleaf:
  3. prefix: classpath:/templates/ # 模板路径

1 楼 ihanfeng 2017-08-31

本例有没有相关代码实例,根据你上面的配置没搞成功,登录后又返回登录页面。

转自:https://www.iteye.com/blog/rensanning-2386553

原文地址:https://www.cnblogs.com/panchanggui/p/12275578.html

时间: 2024-10-02 17:23:50

Spring Security OAuth2 Provider 之 自定义开发的相关文章

OAuth2.0学习(4-99)Spring Security OAuth2.0 开发指南

1.org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter              org.springframework.security.oauth2.provider.client.ClientCredentialsTokenEndpointFilter              org.springframework.security.oauth2.client.fil

spring security oauth2.0 实现

oauth应该属于security的一部分.关于oauth的的相关知识可以查看阮一峰的文章:http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html 一.目标 现在很多系统都支持第三方账号密码等登陆我们自己的系统,例如:我们经常会看到,一些系统使用微信账号,微博账号.QQ账号等登陆自己的系统,我们现在就是要模拟这种登陆的方式,很多大的公司已经实现了这种授权登陆的方式,并提供了相应的API,供我们开发人员调用.他们实际上用的也规范是oauth2.0

Spring Security 入门(1-3)Spring Security oauth2.0 指南

入门 这是支持OAuth2.0的用户指南.对于OAuth1.0,一切都是不同的,所以看它的用户指南. 本用户指南分为两个部分,第一部分是OAuth2.0提供端(OAuth 2.0 Provider),第二部分是OAuth2.0的客户端(OAuth 2.0 Client) OAuth2.0提供端 OAuth2.0的提供端的用途是负责将受保护的资源暴露出去.建立一个可以访问受保护的资源的客户端列表. 提供端是通过管理和验证可用于访问受保护的资源的OAuth 2令牌来做的. 在适当的地方,提供端必须为

springboot+spring security +oauth2.0 demo搭建(password模式)(认证授权端与资源服务端分离的形式)

项目security_simple(认证授权项目) 1.新建springboot项目 这儿选择springboot版本我选择的是2.0.6 点击finish后完成项目的创建 2.引入maven依赖  下面是我引入的依赖 1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi=&q

Spring security oauth2最简单入门环境搭建

关于OAuth2的一些简介,见我的上篇blog:http://wwwcomy.iteye.com/blog/2229889 PS:貌似内容太水直接被鹳狸猿干沉.. 友情提示 学习曲线:spring+spring mvc+spring security+Oauth2基本姿势,如果前面都没看过请及时关闭本网页. 我有信心我的这个blog应该是迄今为止使用spring security oauth2最简单的hello world app介绍了,如果你下下来附件源码还看不懂,请留言.. 其他能搜到的如h

Spring Security 解析(七) —— Spring Security Oauth2 源码解析

Spring Security 解析(七) -- Spring Security Oauth2 源码解析 ??在学习Spring Cloud 时,遇到了授权服务oauth 相关内容时,总是一知半解,因此决定先把Spring Security .Spring Security Oauth2 等权限.认证相关的内容.原理及设计学习并整理一遍.本系列文章就是在学习的过程中加强印象和理解所撰写的,如有侵权请告知. 项目环境: JDK1.8 Spring boot 2.x Spring Security

【OAuth2.0】Spring Security OAuth2.0篇之初识

不吐不快 因为项目需求开始接触OAuth2.0授权协议.断断续续接触了有两周左右的时间.不得不吐槽的,依然是自己的学习习惯问题,总是着急想了解一切,习惯性地钻牛角尖去理解小的细节,而不是从宏观上去掌握,或者说先用起来(少年,一辈子辣么长,你这么着急合适吗?).好在前人们已经做好了很好的demo,我自己照着抄一抄也就理解了大概如何用,依旧手残党,依旧敲不出好代码.忏悔- WHAT? 项目之中实际使用OAuth2.0实现是用的Spring Security OAuth2.0,一套基于Spring S

spring security oauth2.0 实现 解决url-pattern .do .action

参考以下两个文章: http://www.cnblogs.com/0201zcr/p/5328847.html http://wwwcomy.iteye.com/blog/2230265 web.xml 注意这里的<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>   <url-pattern>/*</url-pattern>  而<serv

Spring Security OAuth2 Demo -- good

1. 添加依赖授权服务是基于Spring Security的,因此需要在项目中引入两个依赖: <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-security</artifactId> </dependency> <dependency> <groupId>org.springf