![](/img/trans.png)
[英]Implementing Oauth2 with spring security in web application
[英]Web and Mobile Clients for Spring Security OAuth2
我試圖圍繞OAuth2和Spring Security OAuth,特別是OAuth提供商服務。 我正在嘗試實現以下內容:
所有這些模塊彼此獨立,即在不同的項目中分開,並將托管在不同的域上,例如(1) http://oauth.web.com ,(2) http://rest.web.com , (3) http://web.com
我的兩個問題是:
A.如何實施Web客戶端項目,以便在用戶登錄受保護頁面或單擊“登錄”按鈕時,重定向到OAuth提供者URL,登錄,並在具有所有用戶角色的Web客戶端上進行身份驗證,以及同時需要知道使用了哪個客戶端。 @EnableResourceServer
(與實現資源服務器的方式相同;請參閱下面的代碼)以獲取用戶的詳細信息? 我是否必須管理訪問令牌並始終將其包含在對資源服務器的調用中,或者它可以以某種方式自動完成?
B.在我將要開發的移動應用程序上實現安全性的最佳方法是什么。 我是否應該使用密碼宏來進行此身份驗證,因為應用程序將由我構建,我將在本機屏幕中將用戶名和密碼作為基本身份驗證通過SSL發送到服務器? 是否有任何示例我可以查看與Spring Security OAuth的對話並返回用戶詳細信息。
這是我對OAuth項目(1)和資源項目(2)的實現:
OAuth2服務器配置(大部分代碼來自HERE )
@Configuration
@EnableAuthorizationServer
public class OAuth2ServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Autowired
DataSource dataSource;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints
.tokenStore(tokenStore())
.approvalStore(approvalStore())
.authorizationCodeServices(authorizationCodeServices())
;
}
@Bean
public JdbcClientDetailsService clientDetailsService() {
return new JdbcClientDetailsService(dataSource);
}
@Bean
public TokenStore tokenStore() {
return new JdbcTokenStore(dataSource);
}
@Bean
public ApprovalStore approvalStore() {
return new JdbcApprovalStore(dataSource);
}
@Bean
public AuthorizationCodeServices authorizationCodeServices() {
return new JdbcAuthorizationCodeServices(dataSource);
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(clientDetailsService());
}
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer.checkTokenAccess("permitAll()");
}
}
網絡安全配置
@Configuration
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER)
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
@Autowired
private CustomUserDetailsService customUserDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable(); // TODO. Enable this!!!
http.authorizeRequests()
.and()
.formLogin()
// .loginPage("/login") // manually defining page to login
// .failureUrl("/login?error") // manually defining page for login error
.usernameParameter("email")
.permitAll()
.and()
.logout()
// .logoutUrl("/logout")
.logoutSuccessUrl("/")
.permitAll();
}
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(customUserDetailsService)
.passwordEncoder(new BCryptPasswordEncoder());
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
UserDetailsService(customUserDetailsService)
@Service
public class CustomUserDetailsService implements UserDetailsService{
private final UserService userService;
@Autowired
public CustomUserDetailsService(UserService userService) {
this.userService = userService;
}
public Authority loadUserByUsername(String email) throws UsernameNotFoundException {
User user = userService.getByEmail(email)
.orElseThrow(() -> new UsernameNotFoundException(String.format("User with email=%s was not found", email)));
return new Authority(user);
}
}
配置(大部分框架代碼都來自此示例)
@Configuration
@EnableResourceServer
public class OAuth2ResourceConfig extends ResourceServerConfigurerAdapter{
@Autowired
DataSource dataSource;
String RESOURCE_ID = "data_resource";
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
TokenStore tokenStore = new JdbcTokenStore(dataSource);
resources
.resourceId(RESOURCE_ID)
.tokenStore(tokenStore);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
// For some reason we cant just "permitAll" OPTIONS requests which are needed for CORS support. Spring Security
// will respond with an HTTP 401 nonetheless.
// So we just put all other requests types under OAuth control and exclude OPTIONS.
.authorizeRequests()
.antMatchers(HttpMethod.GET, "/**").access("#oauth2.hasScope('read')")
.antMatchers(HttpMethod.POST, "/**").access("#oauth2.hasScope('write')")
.antMatchers(HttpMethod.PATCH, "/**").access("#oauth2.hasScope('write')")
.antMatchers(HttpMethod.PUT, "/**").access("#oauth2.hasScope('write')")
.antMatchers(HttpMethod.DELETE, "/**").access("#oauth2.hasScope('write')")
.and()
// Add headers required for CORS requests.
.headers().addHeaderWriter((request, response) -> {
response.addHeader("Access-Control-Allow-Origin", "*");
if (request.getMethod().equals("OPTIONS")) {
response.setHeader("Access-Control-Allow-Methods", request.getHeader("Access-Control-Request-Method"));
response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Request-Headers"));
}
});
}
}
WS控制器:
@RestController
@RequestMapping(value = "/todos")
public class TodoController {
@Autowired
private TodoRepository todoRepository;
@RequestMapping(method = RequestMethod.GET)
public List<Todo> todos() {
return todoRepository.findAll();
}
// other methods
}
如何實現Web客戶端項目,以便在用戶登錄受保護頁面或單擊“登錄”按鈕時,重定向到OAuth提供程序URL,登錄,並在具有所有用戶角色的Web客戶端上進行身份驗證,以及需要知道使用了哪個客戶端
您希望將OAuth用作SSO。
選項1,使用spring cloud https://spring.io/blog/2015/02/03/sso-with-oauth2-angular-js-and-spring-security-part-v
選項2,手動處理SSO過程:
在您的Web客戶端中,使用授權授權將登錄頁面配置為OAuth服務器。
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable(); // TODO. Enable this!!!
http.authorizeRequests()
.and()
.formLogin()
.loginPage("http://oauth.web.com/oauth/authorize?response_type=code&client_id=webclient&redirect_uri=http://web.com") // manually defining page to login
//.failureUrl("/login?error") // manually defining page for login error
.usernameParameter("email")
.permitAll()
.and()
.logout()
//.logoutUrl("/logout")
.logoutSuccessUrl("/")
.permitAll();
}
身份驗證和授權過程完成后,您將被重定向到具有授權碼http://web.com/?code=jYWioI
Web客戶端。 您的Web客戶端應該在您的oauth服務器上使用令牌訪問權交換此代碼。 在您的oauth服務器上,創建用於檢索用戶信息的端點
@RestController
public class UserRestService {
@RequestMapping("/user")
public Principal user(Principal user) {
// you can also return User object with it's roles
// {"details":...,"principal":{"username":"user",...},"name":"user"}
return user;
}
}
然后,您的Web客戶端可以通過發送具有對上述休息端點的令牌訪問權限的請求來訪問用戶詳細信息,並根據響應對用戶進行身份驗證。
我是否必須管理訪問令牌並始終將其包含在對資源服務器的調用中,或者它可以以某種方式自動完成?
每個請求都必須包含令牌訪問。 如果你想自動完成,spring提供了Oauth 2客戶端http://projects.spring.io/spring-security-oauth/docs/oauth2.html
在我將要開發的移動應用程序上實現安全性的最佳方法是什么。 我是否應該使用密碼宏來進行此身份驗證,因為應用程序將由我構建,我將在本機屏幕中將用戶名和密碼作為基本身份驗證通過SSL發送到服務器?
由於您使用的是本機屏幕,因此密碼授予就足夠了,但您可以存儲刷新令牌,這樣您就可以請求令牌訪問而無需重復身份驗證過程。
是否有任何示例我可以查看與Spring Security OAuth的對話並返回用戶詳細信息。
請參閱上面的示例代碼或查看此https://spring.io/blog/2015/02/03/sso-with-oauth2-angular-js-and-spring-security-part-v
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.