使用OAuth2安全的Spring security REST API(含demo代码下载)

位置:首页>文章>详情   分类: 教程分享 > Java教程   阅读(4894)   2023-03-28 11:29:14

    让我们Spring REST API使用OAuth2这个时间来保护我们,这是一个简单的指南,显示使用REST API来保护REST API所需的内容Spring OAuth2。我们的用例符合Resource-owner Password GrantOAUth2规范的流程。我们将使用两个不同的客户端(Postman和Spring RestTemplate基于Java 的应用程序)访问我们的OAuth2受保护的REST资源。

    如果您已经熟悉OAuth2概念,您可能希望跳过该理论,并直接跳转到代码中。一如以往,在本文末尾附件中可以找到完整的代码。让我们开始吧。
 

    什么是OAuth2

    OAuth2是一个标准化的授权协议/框架。根据官方OAuth2规范:

    OAuth 2.0授权框架使得第三方应用程序可以通过协调资源所有者和HTTP服务之间的批准交互来代替资源所有者来获取对HTTP服务的有限访问权限,也可以允许第三方应用程序以自己的身份获得访问权限。

    Google,Facebook等大型玩家已经在使用自己的OAuth2实现了很长一段时间。企业也正在朝OAuth2采纳方向发展。

我发现OAuth2规范比较简单。然而,如果你想开始更快,可以在这里找到一篇关于OAuth2基础知识的优秀文章,从而深入了解OAUth2理论概念。

Spring Security OAuth项目提供了使用Spring开发符合OAuth2标准的实现所需的所有API。官方的Spring安全oauth项目提供了一个实施OAuth2的综合示例。这个帖子的代码示例灵感来自这个例子本身。这篇文章的目的是为了保护我们的REST API,只需使用所需的最低限度的功能。

至少你应该知道OAuth2中的四个关键概念:
 

OAuth2角色

OAuth2定义了四个角色:

  • resource owner
    可能是你 能够授予访问受保护资源的实体。当资源所有者是个人时,它被称为最终用户。
  • resource server
    托管受保护资源的服务器,能够使用访问令牌接受和响应受保护的资源请求。
  • client
    代表资源所有者及其授权的应用程序生成受保护的资源请求。它可能是一个移动应用程序,要求您访问您的Facebook订阅源,REST客户端尝试访问REST API,一个网站[Stackoverflow例如]使用Facebook帐户提供备用登录选项。
  • authorization server
    服务器在成功验证资源所有者并获得授权后,向客户端发出访问令牌。

在我们的示例中,我们的REST API只能通过资源服务器进行访问,这将需要存在请求的访问令牌
 

2. OAuth2授权授权类型

授权授权是表示资源所有者授权(访问其受保护的资源)的凭据,由客户端使用以获取访问令牌。规范定义了四种授权类型:

  • authorization code
  • implicit
  • resource owner password credentials
  • client credentials

我们将使用resource owner password credentials授权类型。原因很简单,我们没有实现将我们重定向到登录页面的视图。仅客户端[Postman或RestTemplate为基础的Java客户端例如]拥有资源所有者的凭据,并且他们将这些凭证以及客户机凭证提供给授权服务器,以便最终接收访问令牌[和可选刷新令牌],然后使用该令牌实际访问资源。

一个常见的例子是GMail app您的智能手机上的[客户端],您需要您的凭据并使用它们进行连接GMail servers。它还显示“密码凭证授予”最适合当客户端和服务器与信任在同一个公司时,您不想向第三方提供凭据。

OAuth2令牌

令牌是实现特定的随机字符串,由授权服务器生成,并在客户端请求时发出。

  • Access Token :发送每个请求,通常有效期很短的一段时间[一小时例如]
  • Refresh Token :主要用于获取新的访问令牌,不发送每个请求,通常比访问令牌寿命更长。
HTTPS上的一个词:对于任何类型的安全实现,从基本身份验证到完整的OAuth2实现HTTPS都是必须的。没有HTTPS,无论您的实现是什么,安全性都将受到威胁。

OAuth2访问令牌范围

客户端可以使用范围[想要访问此用户的Facebook帐户的Feed和照片]来查询具有特定访问权限的资源,授权服务器又返回显示实际授予客户端访问权限的范围[资源所有者只允许Feed访问,没有照片例如]。


我们进入代码

我们来实现使用Spring Security实现OAuth的必要构建块,以便访问我们的REST资源。

资源服务器

资源服务器托管客户端感兴趣的资源[我们的REST API]。资源位于/user/@EnableResourceServer注释,应用于OAuth2资源服务器,启用使用传入OAuth2令牌对请求进行身份验证的Spring Security过滤器。类ResourceServerConfigurerAdapter实现ResourceServerConfigurer提供了调整由OAuth2安全保护的访问规则和路径的方法。

package com.websystique.springmvc.security;
 
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;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.error.OAuth2AccessDeniedHandler;
 
@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
 
    private static final String RESOURCE_ID = "my_rest_api";
     
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources.resourceId(RESOURCE_ID).stateless(false);
    }
 
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.
        anonymous().disable()
        .requestMatchers().antMatchers("/user/**")
        .and().authorizeRequests()
        .antMatchers("/user/**").access("hasRole('ADMIN')")
        .and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());
    }
 
}


授权服务器是一个负责验证凭据的人员,如果凭据确定,提供令牌[刷新令牌以及访问令牌]。它还包含有关注册的客户端和可能的访问范围和授权类型的信息。令牌存储用于存储令牌。我们将使用内存中的令牌存储。@EnableAuthorizationServer在当前应用程序上下文中启用授权服务器(即AuthorizationEndpoint和TokenEndpoint)。类AuthorizationServerConfigurerAdapter实现AuthorizationServerConfigurer,它提供了配置授权服务器的所有必要方法。2.授权服务器


package com.websystique.springmvc.security;
 
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.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;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.approval.UserApprovalHandler;
import org.springframework.security.oauth2.provider.token.TokenStore;
 
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
 
    private static String REALM="MY_OAUTH_REALM";
     
    @Autowired
    private TokenStore tokenStore;
 
    @Autowired
    private UserApprovalHandler userApprovalHandler;
 
    @Autowired
    @Qualifier("authenticationManagerBean")
    private AuthenticationManager authenticationManager;
 
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
 
        clients.inMemory()
            .withClient("my-trusted-client")
            .authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
            .authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
            .scopes("read", "write", "trust")
            .secret("secret")
            .accessTokenValiditySeconds(120).//Access token is only valid for 2 minutes.
            refreshTokenValiditySeconds(600);//Refresh token is only valid for 10 minutes.
    }
 
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(tokenStore).userApprovalHandler(userApprovalHandler)
                .authenticationManager(authenticationManager);
    }
 
    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer.realm(REALM+"/client");
    }
 
}



向客户端注册客户端“我的信任客户端”和密码“秘密”以及允许的角色和范围。以上配置

  • 指定任何生成的访问令牌只有120秒有效
  • 指定任何生成的刷新令牌只有600秒有效

3.安全配置

粘在一起 端点/oauth/token用于请求令牌[访问或刷新]。资源所有者[bill,bob]在这里配置。

package com.websystique.springmvc.security;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.approval.ApprovalStore;
import org.springframework.security.oauth2.provider.approval.TokenApprovalStore;
import org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler;
import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
 
@Configuration
@EnableWebSecurity
public class OAuth2SecurityConfiguration extends WebSecurityConfigurerAdapter {
 
    @Autowired
    private ClientDetailsService clientDetailsService;
     
    @Autowired
    public void globalUserDetails(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
        .withUser("bill").password("abc123").roles("ADMIN").and()
        .withUser("bob").password("abc123").roles("USER");
    }
 
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
        .csrf().disable()
        .anonymous().disable()
        .authorizeRequests()
        .antMatchers("/oauth/token").permitAll();
    }
 
    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
 
 
    @Bean
    public TokenStore tokenStore() {
        return new InMemoryTokenStore();
    }
 
    @Bean
    @Autowired
    public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore){
        TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler();
        handler.setTokenStore(tokenStore);
        handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
        handler.setClientDetailsService(clientDetailsService);
        return handler;
    }
     
    @Bean
    @Autowired
    public ApprovalStore approvalStore(TokenStore tokenStore) throws Exception {
        TokenApprovalStore store = new TokenApprovalStore();
        store.setTokenStore(tokenStore);
        return store;
    }
     
}

另外,启用全局方法安全性,如果我们想要使用它,它将激活@PreFilter,@PostFilter,@PreAuthorize @PostAuthorize注释。


package com.websystique.springmvc.security;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.expression.method.MethodSecurityExpressionHandler;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.method.configuration.GlobalMethodSecurityConfiguration;
import org.springframework.security.oauth2.provider.expression.OAuth2MethodSecurityExpressionHandler;
 
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, proxyTargetClass = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
    @Autowired
    private OAuth2SecurityConfiguration securityConfig;
 
    @Override
    protected MethodSecurityExpressionHandler createExpressionHandler() {
        return new OAuth2MethodSecurityExpressionHandler();
    }
}

4.终点及其目的

  • 尝试访问资源[REST API],无需任何授权[将当然失败]。
    GET http://localhost:8080/SpringSecurityOAuth2Example/user/
  • 问令牌[接入+刷新]使用HTTP POST/oauth/token,与grant_type =密码和资源所有者凭证REQ-PARAMS。另外,在授权头中发送客户端凭据。

     

    POST http://localhost:8080/SpringSecurityOAuth2Example/oauth/token?grant_type=password&username=bill&password=abc123

  • 要求通过有效的刷新令牌新的访问令牌,使用HTTP POST/oauth/token,与grant_type = refresh_token,并发送实际的刷新令牌。另外,在授权头中发送客户端凭据。

     

    POST http://localhost:8080/SpringSecurityOAuth2Example/oauth/token?grant_type=refresh_token&refresh_token=094b7d23-973f-4cc1-83ad-8ffd43de1845

  • 通过使用access_token具有请求的查询参数提供访问令牌来访问资源。
    GET http://localhost:8080/SpringSecurityOAuth2Example/user/?access_token=3525d0e4-d881-49e7-9f91-bcfd18259109

5.休息API

我在大部分帖子中使用的简单的Spring REST API。


package com.websystique.springmvc.controller;
  
import java.util.List;
  
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.util.UriComponentsBuilder;
  
import com.websystique.springmvc.model.User;
import com.websystique.springmvc.service.UserService;
  
@RestController
public class HelloWorldRestController {
  
    @Autowired
    UserService userService;  //Service which will do all data retrieval/manipulation work
  
      
    //-------------------Retrieve All Users--------------------------------------------------------
      
    @RequestMapping(value = "/user/", method = RequestMethod.GET)
    public ResponseEntity<List<User>> listAllUsers() {
        List<User> users = userService.findAllUsers();
        if(users.isEmpty()){
            return new ResponseEntity<List<User>>(HttpStatus.NO_CONTENT);//You many decide to return HttpStatus.NOT_FOUND
        }
        return new ResponseEntity<List<User>>(users, HttpStatus.OK);
    }
  
  
    //-------------------Retrieve Single User--------------------------------------------------------
      
    @RequestMapping(value = "/user/{id}", method = RequestMethod.GET, produces = {MediaType.APPLICATION_JSON_VALUE,MediaType.APPLICATION_XML_VALUE})
    public ResponseEntity<User> getUser(@PathVariable("id") long id) {
        System.out.println("Fetching User with id " + id);
        User user = userService.findById(id);
        if (user == null) {
            System.out.println("User with id " + id + " not found");
            return new ResponseEntity<User>(HttpStatus.NOT_FOUND);
        }
        return new ResponseEntity<User>(user, HttpStatus.OK);
    }
  
      
      
    //-------------------Create a User--------------------------------------------------------
      
    @RequestMapping(value = "/user/", method = RequestMethod.POST)
    public ResponseEntity<Void> createUser(@RequestBody User user, UriComponentsBuilder ucBuilder) {
        System.out.println("Creating User " + user.getName());
  
        if (userService.isUserExist(user)) {
            System.out.println("A User with name " + user.getName() + " already exist");
            return new ResponseEntity<Void>(HttpStatus.CONFLICT);
        }
  
        userService.saveUser(user);
  
        HttpHeaders headers = new HttpHeaders();
        headers.setLocation(ucBuilder.path("/user/{id}").buildAndExpand(user.getId()).toUri());
        return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
    }
  
      
    //------------------- Update a User --------------------------------------------------------
      
    @RequestMapping(value = "/user/{id}", method = RequestMethod.PUT)
    public ResponseEntity<User> updateUser(@PathVariable("id") long id, @RequestBody User user) {
        System.out.println("Updating User " + id);
          
        User currentUser = userService.findById(id);
          
        if (currentUser==null) {
            System.out.println("User with id " + id + " not found");
            return new ResponseEntity<User>(HttpStatus.NOT_FOUND);
        }
  
        currentUser.setName(user.getName());
        currentUser.setAge(user.getAge());
        currentUser.setSalary(user.getSalary());
          
        userService.updateUser(currentUser);
        return new ResponseEntity<User>(currentUser, HttpStatus.OK);
    }
  
    //------------------- Delete a User --------------------------------------------------------
      
    @RequestMapping(value = "/user/{id}", method = RequestMethod.DELETE)
    public ResponseEntity<User> deleteUser(@PathVariable("id") long id) {
        System.out.println("Fetching & Deleting User with id " + id);
  
        User user = userService.findById(id);
        if (user == null) {
            System.out.println("Unable to delete. User with id " + id + " not found");
            return new ResponseEntity<User>(HttpStatus.NOT_FOUND);
        }
  
        userService.deleteUserById(id);
        return new ResponseEntity<User>(HttpStatus.NO_CONTENT);
    }
  
      
    //------------------- Delete All Users --------------------------------------------------------
      
    @RequestMapping(value = "/user/", method = RequestMethod.DELETE)
    public ResponseEntity<User> deleteAllUsers() {
        System.out.println("Deleting All Users");
  
        userService.deleteAllUsers();
        return new ResponseEntity<User>(HttpStatus.NO_CONTENT);
    }
  
}


运行应用程序

运行它并使用两个不同的客户端进行测试。

 

客户端1:Postman

尝试访问一个没有任何信息的资源,将获得一个401。

SpringOAuth2_img1

让我们得到令牌。首先添加一个客户端凭证 [my-trusted-client / secret] 的授权头文件。

SpringOAuth2_img2

单击更新请求,验证标题标签中的标题。

SpringOAuth2_img3

发送POST请求时,您将收到包含响应access-token以及refresh-token

SpringOAuth2_img4

将这些令牌保存在某个地方,您将需要它们。现在,您可以使用此访问令牌(有效期为2分钟)来访问资源。

SpringOAuth2_img5

2分钟后,access-token将过期,您的进一步资源请求将失败。

SpringOAuth2_img6

我们需要一个新的访问令牌。通过刷新令牌来触发一个帖子,以获得全新的访问令牌。

SpringOAuth2_img7

使用这个新的访问令牌访问资源。

SpringOAuth2_img8

刷新令牌也过期[10分钟]。之后,您将看到刷新请求失败。

SpringOAuth2_img9

这意味着您需要请求新的刷新+访问令牌,如步骤2中所示。

客户端2:基于RestTemplate的java应用程序

方法sendTokenRequest用于实际获取令牌。然后,我们收到的访问令牌将被用于每个请求。如果需要,您可以在下面的示例中轻松实现刷新令牌流。

package com.websystique.springmvc;
  
import java.net.URI;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
 
import org.apache.commons.codec.binary.Base64;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.util.Assert;
import org.springframework.web.client.RestTemplate;
 
import com.websystique.springmvc.model.AuthTokenInfo;
import com.websystique.springmvc.model.User;
  
public class SpringRestClient {
  
    public static final String REST_SERVICE_URI = "http://localhost:8080/SpringSecurityOAuth2Example";
     
    public static final String AUTH_SERVER_URI = "http://localhost:8080/SpringSecurityOAuth2Example/oauth/token";
     
    public static final String QPM_PASSWORD_GRANT = "?grant_type=password&username=bill&password=abc123";
     
    public static final String QPM_ACCESS_TOKEN = "?access_token=";
 
    /*
     * Prepare HTTP Headers.
     */
    private static HttpHeaders getHeaders(){
        HttpHeaders headers = new HttpHeaders();
        headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
        return headers;
    }
     
    /*
     * Add HTTP Authorization header, using Basic-Authentication to send client-credentials.
     */
    private static HttpHeaders getHeadersWithClientCredentials(){
        String plainClientCredentials="my-trusted-client:secret";
        String base64ClientCredentials = new String(Base64.encodeBase64(plainClientCredentials.getBytes()));
         
        HttpHeaders headers = getHeaders();
        headers.add("Authorization", "Basic " + base64ClientCredentials);
        return headers;
    }    
     
    /*
     * Send a POST request [on /oauth/token] to get an access-token, which will then be send with each request.
     */
    @SuppressWarnings({ "unchecked"})
    private static AuthTokenInfo sendTokenRequest(){
        RestTemplate restTemplate = new RestTemplate(); 
         
        HttpEntity<String> request = new HttpEntity<String>(getHeadersWithClientCredentials());
        ResponseEntity<Object> response = restTemplate.exchange(AUTH_SERVER_URI+QPM_PASSWORD_GRANT, HttpMethod.POST, request, Object.class);
        LinkedHashMap<String, Object> map = (LinkedHashMap<String, Object>)response.getBody();
        AuthTokenInfo tokenInfo = null;
         
        if(map!=null){
            tokenInfo = new AuthTokenInfo();
            tokenInfo.setAccess_token((String)map.get("access_token"));
            tokenInfo.setToken_type((String)map.get("token_type"));
            tokenInfo.setRefresh_token((String)map.get("refresh_token"));
            tokenInfo.setExpires_in((int)map.get("expires_in"));
            tokenInfo.setScope((String)map.get("scope"));
            System.out.println(tokenInfo);
            //System.out.println("access_token ="+map.get("access_token")+", token_type="+map.get("token_type")+", refresh_token="+map.get("refresh_token")
            //+", expires_in="+map.get("expires_in")+", scope="+map.get("scope"));;
        }else{
            System.out.println("No user exist----------");
             
        }
        return tokenInfo;
    }
     
    /*
     * Send a GET request to get list of all users.
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    private static void listAllUsers(AuthTokenInfo tokenInfo){
        Assert.notNull(tokenInfo, "Authenticate first please......");
 
        System.out.println("\nTesting listAllUsers API-----------");
        RestTemplate restTemplate = new RestTemplate(); 
         
        HttpEntity<String> request = new HttpEntity<String>(getHeaders());
        ResponseEntity<List> response = restTemplate.exchange(REST_SERVICE_URI+"/user/"+QPM_ACCESS_TOKEN+tokenInfo.getAccess_token(),
                HttpMethod.GET, request, List.class);
        List<LinkedHashMap<String, Object>> usersMap = (List<LinkedHashMap<String, Object>>)response.getBody();
         
        if(usersMap!=null){
            for(LinkedHashMap<String, Object> map : usersMap){
                System.out.println("User : id="+map.get("id")+", Name="+map.get("name")+", Age="+map.get("age")+", Salary="+map.get("salary"));;
            }
        }else{
            System.out.println("No user exist----------");
        }
    }
      
    /*
     * Send a GET request to get a specific user.
     */
    private static void getUser(AuthTokenInfo tokenInfo){
        Assert.notNull(tokenInfo, "Authenticate first please......");
        System.out.println("\nTesting getUser API----------");
        RestTemplate restTemplate = new RestTemplate();
        HttpEntity<String> request = new HttpEntity<String>(getHeaders());
        ResponseEntity<User> response = restTemplate.exchange(REST_SERVICE_URI+"/user/1"+QPM_ACCESS_TOKEN+tokenInfo.getAccess_token(),
                HttpMethod.GET, request, User.class);
        User user = response.getBody();
        System.out.println(user);
    }
      
    /*
     * Send a POST request to create a new user.
     */
    private static void createUser(AuthTokenInfo tokenInfo) {
        Assert.notNull(tokenInfo, "Authenticate first please......");
        System.out.println("\nTesting create User API----------");
        RestTemplate restTemplate = new RestTemplate();
        User user = new User(0,"Sarah",51,134);
        HttpEntity<Object> request = new HttpEntity<Object>(user, getHeaders());
        URI uri = restTemplate.postForLocation(REST_SERVICE_URI+"/user/"+QPM_ACCESS_TOKEN+tokenInfo.getAccess_token(),
                request, User.class);
        System.out.println("Location : "+uri.toASCIIString());
    }
  
    /*
     * Send a PUT request to update an existing user.
     */
    private static void updateUser(AuthTokenInfo tokenInfo) {
        Assert.notNull(tokenInfo, "Authenticate first please......");
        System.out.println("\nTesting update User API----------");
        RestTemplate restTemplate = new RestTemplate();
        User user  = new User(1,"Tomy",33, 70000);
        HttpEntity<Object> request = new HttpEntity<Object>(user, getHeaders());
        ResponseEntity<User> response = restTemplate.exchange(REST_SERVICE_URI+"/user/1"+QPM_ACCESS_TOKEN+tokenInfo.getAccess_token(),
                HttpMethod.PUT, request, User.class);
        System.out.println(response.getBody());
    }
  
    /*
     * Send a DELETE request to delete a specific user.
     */
    private static void deleteUser(AuthTokenInfo tokenInfo) {
        Assert.notNull(tokenInfo, "Authenticate first please......");
        System.out.println("\nTesting delete User API----------");
        RestTemplate restTemplate = new RestTemplate();
        HttpEntity<String> request = new HttpEntity<String>(getHeaders());
        restTemplate.exchange(REST_SERVICE_URI+"/user/3"+QPM_ACCESS_TOKEN+tokenInfo.getAccess_token(),
                HttpMethod.DELETE, request, User.class);
    }
  
  
    /*
     * Send a DELETE request to delete all users.
     */
    private static void deleteAllUsers(AuthTokenInfo tokenInfo) {
        Assert.notNull(tokenInfo, "Authenticate first please......");
        System.out.println("\nTesting all delete Users API----------");
        RestTemplate restTemplate = new RestTemplate();
        HttpEntity<String> request = new HttpEntity<String>(getHeaders());
        restTemplate.exchange(REST_SERVICE_URI+"/user/"+QPM_ACCESS_TOKEN+tokenInfo.getAccess_token(),
                HttpMethod.DELETE, request, User.class);
    }
  
    public static void main(String args[]){
        AuthTokenInfo tokenInfo = sendTokenRequest();
        listAllUsers(tokenInfo);
         
        getUser(tokenInfo);
         
        createUser(tokenInfo);
        listAllUsers(tokenInfo);
         
        updateUser(tokenInfo);
        listAllUsers(tokenInfo);
         
        deleteUser(tokenInfo);
        listAllUsers(tokenInfo);
         
        deleteAllUsers(tokenInfo);
        listAllUsers(tokenInfo);
    }
}

以上代码将产生以下输出:
AuthTokenInfo [access_token=fceed386-5923-4bf8-b193-1d76f95da4c4, token_type=bearer, refresh_token=29d28ee2-9d09-483f-a2d6-7f93e7a31667, expires_in=71, scope=read write trust]
 
Testing listAllUsers API-----------
User : id=1, Name=Sam, Age=30, Salary=70000.0
User : id=2, Name=Tom, Age=40, Salary=50000.0
User : id=3, Name=Jerome, Age=45, Salary=30000.0
User : id=4, Name=Silvia, Age=50, Salary=40000.0
 
Testing getUser API----------
User [id=1, name=Sam, age=30, salary=70000.0]
 
Testing create User API----------
Location : http://localhost:8080/SpringSecurityOAuth2Example/user/5
 
Testing listAllUsers API-----------
User : id=1, Name=Sam, Age=30, Salary=70000.0
User : id=2, Name=Tom, Age=40, Salary=50000.0
User : id=3, Name=Jerome, Age=45, Salary=30000.0
User : id=4, Name=Silvia, Age=50, Salary=40000.0
User : id=5, Name=Sarah, Age=51, Salary=134.0
 
Testing update User API----------
User [id=1, name=Tomy, age=33, salary=70000.0]
 
Testing listAllUsers API-----------
User : id=1, Name=Tomy, Age=33, Salary=70000.0
User : id=2, Name=Tom, Age=40, Salary=50000.0
User : id=3, Name=Jerome, Age=45, Salary=30000.0
User : id=4, Name=Silvia, Age=50, Salary=40000.0
User : id=5, Name=Sarah, Age=51, Salary=134.0
 
Testing delete User API----------
 
Testing listAllUsers API-----------
User : id=1, Name=Tomy, Age=33, Salary=70000.0
User : id=2, Name=Tom, Age=40, Salary=50000.0
User : id=4, Name=Silvia, Age=50, Salary=40000.0
User : id=5, Name=Sarah, Age=51, Salary=134.0
 
Testing all delete Users API----------
 
Testing listAllUsers API-----------
No user exist----------
 

项目结构

10

pom.xml

<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>com.websystique.springmvc</groupId>
    <artifactId>SpringSecurityOAuth2Example</artifactId>
    <version>1.0.0</version>
    <packaging>war</packaging>
 
    <name>SpringSecurityOAuth2Example</name>
 
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <springframework.version>4.3.1.RELEASE</springframework.version>
        <springsecurity.version>4.1.1.RELEASE</springsecurity.version>
        <springsecurityoauth2.version>2.0.10.RELEASE</springsecurityoauth2.version>
        <jackson.library>2.7.5</jackson.library>
    </properties>
 
    <dependencies>
        <!-- Spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>${springframework.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${springframework.version}</version>
        </dependency>
 
        <!-- Spring Security -->
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>${springsecurity.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>${springsecurity.version}</version>
        </dependency>
 
        <!-- Spring Security OAuth2-->
        <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
            <version>${springsecurityoauth2.version}</version>
        </dependency>
 
        <!-- Jackson libraries -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson.library}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.dataformat</groupId>
            <artifactId>jackson-dataformat-xml</artifactId>
            <version>${jackson.library}</version>
        </dependency>
 
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
        </dependency>
    </dependencies>
 
    <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.2</version>
                    <configuration>
                        <source>1.7</source>
                        <target>1.7</target>
                    </configuration>
                </plugin>         
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-war-plugin</artifactId>
                    <version>2.4</version>
                    <configuration>
                        <warSourceDirectory>src/main/webapp</warSourceDirectory>
                        <warName>SpringSecurityOAuth2Example</warName>
                        <failOnMissingWebXml>false</failOnMissingWebXml>
                    </configuration>
                </plugin>
            </plugins>
        <finalName>SpringSecurityOAuth2Example</finalName>
    </build>
</project>

下载源代码


 
地址:https://www.leftso.com/article/130.html

相关阅读

本文主要翻译spring官方的基于spring security框架的oauth2开发指南,spring,oauth2,spring框架,Java编程
使用OAuth2安全的Spring REST API,Secure Spring REST API using OAuth2(含demo代码下载)
spring boot 入门之security oauth2 jwt完美整合例子,Java编程中spring boot框架+spring security框架+spring security o...
引言在这篇文章中,我们将讨论如何使用Spring Boot Security OAuth2保护REST API
引言在本文中,我们将讨论有关Spring启动安全性和JWT令牌的OAUTH2实现以及保护REST API
spring boot 2.0 security 5.0 整合,实现自定义表单登录。spring boot 2.0框架使用。
Java编程中spring security4是一个spring框架项目的一个安全方面的项目。主要用于用户认证,授权,角色认证
解决spring security 整合到spring boot中,UserDetailsService接口的loadUserByUsername方法参数username输入为空问题。一  检查...
spring security常用注解@Secured、@PreAuthorize 、@PostAuthorize说明,Java编程,spring security