zoukankan      html  css  js  c++  java
  • springboot2.x实现oauth2授权码登陆

    一 进行授权页

     
    二 使用资源站用户登陆
    自动跨到资源登陆页,先登陆
     

    三 授权资源类型

    登陆成功后,去授权你的资源,这些资源是在AuthorizationServerConfig.configure方法里配置的
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    clients.inMemory()
    .withClient(ClientID)
    .secret(passwordEncoder.encode(ClientSecret))
    .authorizedGrantTypes("authorization_code", "refresh_token",
    "password", "implicit")
    .scopes("read","write","del","userinfo")
    .redirectUris(RedirectURLs);
    }

    四 接到code

    授权之后,系统会重定向到你的redirect_uri这个页面,并带上唯一的code

    五 获取access_token

    我们拿着code就要再去授权服务器去获取token了,你可以在你的代码里写这个,也可以手动拿着code,去拼成一个url,再去拿token,就像这下面的实例。
    注意向oauth/token发的是post请求,client_id和client_secret如果在url上传递,如果在AuthorizationServerConfig类的configure方法中开启allowFormAuthenticationForClients,代码如下
    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
    oauthServer.tokenKeyAccess("isAuthenticated()")
    .checkTokenAccess("permitAll()")
    .allowFormAuthenticationForClients();//支持把secret和clientid写在url上,否则需要在头上
    }
    然后请求后给有下面的响应
    Authorization Ccode------RFRLFY
    access_token_url http://localhost:8081/oauth/token?client_id=android1&code=RFRLFY&grant_type=authorization_code&redirect_uri=http://localhost:8081/callback&client_secret=android1
    Access Token Response ---------{"access_token":"faadf3bf-6488-4036-bc3b-21b0a979602c","token_type":"bearer","refresh_token":"1b01f133-c5ab-419f-8125-088c85916ecb","expires_in":43187,"scope":"read"}

    回调页面代码,主要实现了对code的获取,对access_token的组织,然后请求时把access_token带上,这个方法一般会做成公用的过滤器

    @Controller
    public class UserController {
      @RequestMapping(value = "/callback", method = RequestMethod.GET)
      public ResponseEntity<String> callback(@RequestParam("code") String code) throws JsonProcessingException, IOException {
        ResponseEntity<String> response = null;
        System.out.println("Authorization Ccode------" + code);
        RestTemplate restTemplate = new RestTemplate();
        String access_token_url = "http://localhost:8081/oauth/token";
        access_token_url += "?client_id=android1&code=" + code;
        access_token_url += "&grant_type=authorization_code";
        access_token_url += "&redirect_uri=http://localhost:8081/callback";
        access_token_url += "&client_secret=android1";
        System.out.println("access_token_url " + access_token_url);
        response = restTemplate.exchange(access_token_url, HttpMethod.POST, null, String.class);
        ObjectMapper mapper = new ObjectMapper();
        JsonNode node = mapper.readTree(response.getBody());
        String token = node.path("access_token").asText(); System.out.println("access_token" +access_token);
        String url = "http://localhost:8081/index"; HttpHeaders headers1 = new HttpHeaders(); headers1.add("Authorization", "Bearer " + token); HttpEntity<String> entity = new HttpEntity<>(headers1); ResponseEntity<String> result = restTemplate.exchange(url, HttpMethod.GET, entity, String.class); return result; }

    六 拿着access_token去请求具体的资源

    可以在url地址上直接:http://localhost:8081/index?access_token=faadf3bf-6488-4036-bc3b-21b0a979602c
    七 如何开启oauth scopes授权
    .access("#oauth2.hasScope('del')") 这个需要在ResourceServerConfig.configure里添加它,例如下载代码
    @Configuration
    @EnableResourceServer
    @Order(6)
    public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception {
    http.csrf().disable()//禁用了 csrf 功能
    .authorizeRequests()//限定签名成功的请求
    .antMatchers("/index").access("#oauth2.hasScope('del')") //授权码scopes里需要选中del才可以访问
    .antMatchers("/user").authenticated()//签名成功后可访问,不受role限制
    .anyRequest().permitAll()//其他没有限定的请求,允许访问
    .and().anonymous()//对于没有配置权限的其他请求允许匿名访问
    .and().formLogin()//使用 spring security 默认登录页面
    .and().httpBasic();//启用http 基础验证
     
    }
    }

    八  需要注意的地方

    如果你对用户进行了角色和权限的配置,对于某些保护接口需要有指定权限才能访问的话,需要重getAuthorities方法,否则,你的权限将会失效!

    @Entity
    @Data
    public class User extends BaseEntity implements UserDetails {
      @Id
      @GeneratedValue
      private Long id;
      private String username;
      private String password;
      private String firstName;
      private String lastName;
      @Email
      private String email;
      private String imageUrl;
    
    
      @JsonIgnore
      @ManyToMany(targetEntity = Role.class, fetch = FetchType.EAGER)
      @BatchSize(size = 20)
      private Set<Role> roles = new HashSet<>();
    
      @Transient
      private Set<GrantedAuthority> authorities = new HashSet<>();
    
      /**
       * 注意,这块需要加@Override重写,否则权限无效.
       *
       * @return
       */
      @Override
      public Set<GrantedAuthority> getAuthorities() {
        Set<GrantedAuthority> authorities = new HashSet<>();
        for (Role role : this.roles) {
          for (Authority authority : role.getAuthorities()) {
            authorities.add(new SimpleGrantedAuthority(authority.getValue()));
          }
        }
        return authorities;
      }
    
      @Override
      public boolean isAccountNonExpired() {
        return true;
      }
    
      @Override
      public boolean isAccountNonLocked() {
        return true;
      }
    
      @Override
      public boolean isCredentialsNonExpired() {
        return true;
      }
    
      @Override
      public boolean isEnabled() {
        return true;
      }
    }

    感谢阅读!

  • 相关阅读:
    Java实现 蓝桥杯VIP 算法训练 字符删除
    Java实现 蓝桥杯VIP 算法训练 字符删除
    Java实现 蓝桥杯VIP 算法训练 字符删除
    Java实现 蓝桥杯VIP 算法训练 字符删除
    Java实现 蓝桥杯VIP 算法训练 字符删除
    Java实现 蓝桥杯VIP 算法训练 字符串编辑
    Java实现 蓝桥杯VIP 算法训练 字符串编辑
    Java实现 蓝桥杯VIP 算法训练 字符串编辑
    Java实现 蓝桥杯VIP 算法训练 字符串编辑
    Java实现 蓝桥杯VIP 算法训练 字符串编辑
  • 原文地址:https://www.cnblogs.com/lori/p/11288749.html
Copyright © 2011-2022 走看看