欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring Cloud下基于OAUTH2认证授权(四)

程序员文章站 2022-06-13 15:53:23
...

写在前面:各位看到此博客的小伙伴,如有不对的地方请及时通过私信我或者评论此博客的方式指出,以免误人子弟。多谢!

  之前使用的是oauth2的客户端模式进行的认证授权(即使用客户端id和客户端密码获取token),但到目前为止还没有使用到用户相关的信息,之前项目都是在用户登录的时候判断用户名和密码是否正确,都校验通过后查询用户拥有的角色及菜单,并将用户权限信息放入session,那使用oauth2后怎么结合用户的角色权限保护资源呢?边学习边记录一下使用密码模式认证授权。PS:本篇涉及代码是基于前一篇配置基础之上的。

  想要使用密码验证模式,需要在授权服务器中的AuthorizationServerEndpointsConfigurer中配置authenticationManager,因为默认情况下开启了除了密码类型外的所有验证类型,密码验证只有配置了authenticationManager的配置才会开启,authenticationManager需要配置AuthenticationManager这个Bean,这个Bean需要在WebSecurityConfigurerAdapter中配置。

  于是在WebSecurityConfig类中增加配置AuthenticationManager这个Bean,代码如下:

@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
}

授权服务器中注入authenticationManager,endpoints中配置authenticationManager,代码如下:

@Autowired
private AuthenticationManager authenticationManager;

public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    endpoints
            .tokenStore(tokenStore())
            .authenticationManager(authenticationManager);
}

经过以上两步配置已经开启了密码验证模式,那怎么知道获取token时填写的用户名和密码是否正确呢?那就需要在WebSecurityConfig中配置AuthenticationManagerBuilder(暂且称它为:认证管理器),AuthenticationManagerBuilder并不真正验证用户信息,真正执行认证需要设置userDetailsService(一个实现UserDetailsService接口的类),另外还需要设置密码加密方式,代码如下:

 @Autowired
 private CustomUserDetailsService userDetailsService;
 
 public void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
 }

 

新建CustomUserDetailsService类实现UserDetailsService接口,真正的用户信息验证及验证用户名密码成功后给用户赋权都在这里,代码如下:

@Component
public class CustomUserDetailsService implements UserDetailsService {

    
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        System.out.println("------username------" + username);
        SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority("ROLE_admin");
        List<GrantedAuthority> authorities = new ArrayList<>();
        authorities.add(simpleGrantedAuthority);
        // MTIzNDU2
        return new User(username, "$2a$10$xKE65IFdzlYYrfgZh0C0Qu4gaCQ1TRv1FHHtwR0AL5B2dViAF7vPq", authorities);

    }
}

以上代码仅仅是测试用的,测试数据:用户名随意,密码-123456,使用BCryptPasswordEncoder方式加密后为: $2a1010xKE65IFdzlYYrfgZh0C0Qu4gaCQ1TRv1FHHtwR0AL5B2dViAF7vPq, 用户的权限设置为ROLE_admin,真正使用的时候用户名密码还有权限信息这些应该是从数据库中查询或者调用远程服务获取的用户相关信息。

注意oauth2在验证权限的时候会在权限字符串前自动加上 “ROLE_”,所以我们构建authorities时需要自己把ROLE_追加上。

使用postman测试能否获取到token,测试截图如下:

Spring Cloud下基于OAUTH2认证授权(四)

 

Spring Cloud下基于OAUTH2认证授权(四)

是可以获取到token的,访问受保护的资源/api/test也可以正常返回,所有获取的token也是没问题的,接下来测试下用户的权限是否有效,测试类中新增两个方法,如下:

 @RequestMapping("/api/test1")
 @PreAuthorize("hasRole('admin')")
 public String test1() {
     return "admin";
 }

 @RequestMapping("/api/test2")
 @PreAuthorize("hasRole('common')")
 public String test2() {
     return "common";
 }

使用postman携带token访问/api/test1发现可以访问,并返回admin,访问/api/test2发现返回403,不能访问,

Spring Cloud下基于OAUTH2认证授权(四)

说明在token中携带的用户权限也生效了。

也可以使用浏览器进行测试 不过需要在授权服务器中进行取下配置:
endpoints.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST).

不配置这个的时候携带token访问资源(get请求)是没问题的,但是获取token(post请求)的时候,浏览器会报错:method_not_allowed。