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位随机英数字。
@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;
}
}
效果如下:
(2)自定义生成令牌
默认规则是: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("-", "");
}
}
效果如下:
(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:
@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>
效果如下:
(4)自定义用户登录页面
这部分应该属于SpringSecurity范畴的。
创建用户表
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');
配置SpringSecurity
@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 {
}
用户登录处理部分
@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
}
完成的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
- 大小: 17.6 KB
- 大小: 74.2 KB
- 大小: 26 KB
- 大小: 29.9 KB
- 大小: 15.9 KB
- 大小: 7.7 KB
- 大小: 93.5 KB
分享到:
相关推荐
Spring Security OAuth2 Provider 是一个强大的安全框架,用于构建安全的Web应用和服务。在这个主题中,我们将探讨如何使用Spring Security作为OAuth2提供者,实现第三方登录的简单演示。OAuth2是一种授权框架,允许...
在Spring Boot应用中,通过`spring-boot-starter-data-redis`依赖和`spring.security.oauth2.provider.token.store.redis`配置,可以轻松地将TokenStore切换到Redis。此外,还需要配置Redis连接参数,如主机名、端口...
《Spring Security + OAuth2 + JWT 实现Web安全认证》 在现代Web开发中,安全认证是不可或缺的一部分。Spring Security作为Java领域中强大的安全框架,配合OAuth2和JWT(JSON Web Token),可以构建出高效且安全的...
当我们谈论"springboot与security oauth2整合例子",实际上是在讨论如何将OAuth2协议集成到Spring Boot和Spring Security中,以实现基于令牌(Token)的身份验证和授权机制。OAuth2是一种开放标准,用于授权第三方...
总之,SpringSecurity3.x源码工程是一个宝贵的教育资源,可以帮助开发者从底层理解这个框架的工作原理,并能据此实现自定义的安全解决方案。无论是初学者还是经验丰富的开发者,都能从中受益匪浅。
5. **自定义逻辑**:可能需要根据实际需求扩展或定制Spring Security和CAS的行为,比如添加自定义认证处理器、权限判定逻辑等。 6. **测试与调试**:创建一些受保护的端点并进行测试,确保用户能够正确地通过CAS...
Spring Security允许开发者通过自定义Filter、Provider、AuthenticationManager等来扩展其功能。例如,可以创建自定义的AuthenticationProvider来实现特定的认证逻辑,或者创建自定义的AccessDecisionVoter来执行...
"springsecurity-namespace"可能指的是Spring Security的XML命名空间配置。在Spring Security的早期版本中,使用XML配置是最常见的实践。例如,你可能会看到以下片段: ```xml **" access="hasRole('ROLE_ADMIN')...
在"SpringSecurity权限管理开发手册.pdf"和"SpringSecurity权限管理开发手册.pdf.txt"中,你将找到更多关于如何配置和使用SpringSecurity进行权限管理的详细信息,包括配置XML或Java配置、定义访问规则、处理未授权...
**Spring Security新手入门级Maven实例...随着对Spring Security的深入学习,你将能够实现更复杂的场景,如OAuth2集成、记住我功能、CSRF防护、基于URL的访问控制等。不断实践和探索,你将成为Spring Security的专家。
- **OAuth2 Provider**: 使用Spring Security OAuth2模块,我们可以轻松创建一个OAuth2授权服务器。 - **Authorization Code Grant Flow**: OAuth2中最常见的授权类型,用户通过浏览器重定向到授权服务器进行身份...
在上面的代码中,我们使用 Spring Security 的 Java 配置方式,注册了我们的自定义 AuthenticationProvider 到 Spring Security 中。 最后,我们可以在应用程序中使用我们的自定义 AuthenticationProvider 进行身份...
Spring Security是Spring框架的一个核心组件,专注于提供全面的安全解决方案,包括认证、授权和访问控制。在Spring Security 4.0.1版本中,这个框架引入了一些重要的改进和更新,以增强其性能和安全性。 首先,...
为了实现这些功能,开发者可能需要配置Spring Security的OAuth2 Resource Server,以处理来自OAuth2 Provider的令牌。同时,还需要设置Authorization Server来处理用户的登录、授权请求,生成访问令牌。这些令牌可以...
13. **Custom Authentication Provider**:如果你需要自定义身份验证逻辑,可以实现Spring Security的AuthenticationProvider接口。 14. **Scope**:OAuth2的scope定义了应用可以访问的资源范围,例如只读访问或...
Spring Security还支持OAuth2,可以与其他服务进行安全交互,如Google、Facebook登录。 ### 8. 实战案例 - **防止CSRF攻击**:Spring Security默认开启CSRF保护,可通过配置禁用或调整策略。 - **RESTful API安全*...
- **OAuth2集成**: 如何使用Spring Security与OAuth2结合,实现第三方登录功能。 - **CORS支持**: 设置跨域请求的安全策略,允许不同源的Web应用进行交互。 - **国际化的错误处理**: 如何定制Spring Security的...
Spring Security也支持OAuth2,可以实现第三方登录功能,如Google、Facebook登录。通过OAuth2,Spring Security可以帮助应用保护API,只允许经过授权的客户端访问。 **源码分析** 深入理解Spring Security需要研究...
Spring Security提供了一套灵活的机制来处理这些验证过程,包括自定义认证提供者(Authentication Provider)。 三、授权与访问控制 授权是决定已认证的用户可以访问哪些资源的过程。Spring Security通过访问决策...
import org.springframework.security.oauth2.provider.userDetailsService; import org.springframework.stereotype.Component; import javax.annotation.Resource; import org.springframework.cache.ehcache....