0
点赞
收藏
分享

微信扫一扫

ProjectDay15

吓死我了_1799 2022-03-24 阅读 15
java

续 实现授权服务器

编写登录用配置类

上次课我们已经在sys模块中编写准备好了3个Rest接口

1.根据用户名获得用户对象

2.根据用户id获得所有权限

3.根据用户id获得所有角色

下面要在knows-auth模块编写登录配置类UserDetailsServiceImpl来实现根据用户名返回Spring-Security框架需要的UserDetails对象的方法以便支持登录验证

auth模块创建service包

包中创建UserDetailsServiceImpl类

和单体portal项目登录配置思路一致,但是用户相关的信息要修改为Ribbon调用,最终代码如下

// 当前登录配置类需要保存到Spring容器
@Component
public class UserDetailsServiceImpl implements UserDetailsService {

    @Resource
    private RestTemplate restTemplate;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 1.根据用户名获得用户对象
        String url="http://sys-service/v1/auth/user?username={1}";
        User user=restTemplate
                .getForObject(url , User.class , username);
        // 2.判断查询出来的用户是否存在
        if(user==null){
            // 如果用户对象为空,抛出异常表示登录失败
            //throw new ServiceException("用户名密码错误!");
            throw new UsernameNotFoundException("用户名密码错误!");
        }
        // 3.根据用户id查询用户所有权限
        url="http://sys-service/v1/auth/permissions?id={1}";
        // Ribbon请求的控制器方法返回值为List时
        // 要使用该List泛型类型的数组来接收
        Permission[] permissions=restTemplate
              .getForObject(url , Permission[].class , user.getId());
        // 4.根据用户id查询用户所有角色
        url="http://sys-service/v1/auth/roles?id={1}";
        Role[] roles=restTemplate
              .getForObject(url , Role[].class , user.getId());
        // 5.将权限和角色保存在auth数组中
        String[] auth=new String[permissions.length+roles.length];
        // 分别遍历权限和角色数组,将权限和角色的名称保存在auth数组中
        int i=0;
        for(Permission p: permissions){
            auth[i++]=p.getName();
        }
        for(Role r: roles){
            auth[i++]=r.getName();
        }
        // 6.创建UserDetails对象
        UserDetails details= org.springframework.security
                .core.userdetails.User.builder()
                .username(user.getUsername())
                .password(user.getPassword())
                .authorities(auth)
                .accountLocked(user.getLocked()==1)  //是否锁定(false表示不锁定)
                .disabled(user.getEnabled()==0)   // 是否可用 (false表示可用)
                .build();
        // 7.千万别忘了返回 details!!!
        return details;
    }
}

上面的代码是关键的登录配置

必须测试一下才能安心使用

auth模块的test文件夹下编写测试代码如下

@Resource
UserDetailsServiceImpl userDetailsService;
@Test
void contextLoads() {
    UserDetails details=userDetailsService
            .loadUserByUsername("st2");
    System.out.println(details);
    // Nacos和sys先启动,在运行测试!
}

运行结果可能是:

org.springframework.security.core.userdetails.User@1bdf1: Username: st2; 
Password: [PROTECTED]; 
Enabled: true; 
AccountNonExpired: true; 
credentialsNonExpired: true; 
AccountNonLocked: true; 
Granted Authorities: /index.html,/question/create,/question/detail,/question/uploadMultipleFile,ROLE_STUDENT

要保证Nacos启动并且sys模块启动

运行能输出用户信息表示一切正常

授权服务器核心配置

上面所有编写的类和代码都是为了核心配置做准备的

核心配置就是再创建一个类,这个类要继承一个父类

重写这个父类的三个方法,这三个方法的作用分别是

1.配置授权服务器的各种参数

2.配置客户端对应的各种权限

3.配置客户端允许使用的功能

security包中创建该类

AuthorizationServer(授权服务器)

@Configuration
// 这个注解表示当前类时Oauth2标准下实现的授权服务器配置类
// 表示启动授权服务器相关功能
@EnableAuthorizationServer
public class AuthorizationServer extends
                        AuthorizationServerConfigurerAdapter {
    // 添加依赖注入的对象,它们大多是之前课程中向Spring容器中保存准备好的配置
    // Spring-Security框架的授权管理器,Oauth2要使用
    @Resource
    private AuthenticationManager authenticationManager;
    // 要登录肯定需要登录配置类
    @Resource
    private UserDetailsServiceImpl userDetailsService;

    // 核心配置方法1:配置授权服务器的各种参数
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        // Oauth2框架提供了很多控制器方法
        // 所以我们配置的就是这些控制器方法运行的内容
        // endpoints(端点)参数其实就是控制器方法的功能

        // 配置登录时的授权管理器
        endpoints.authenticationManager(authenticationManager)
                // 设置登录配置类
                .userDetailsService(userDetailsService)
                // 配置登录允许的提交方式
                .allowedTokenEndpointRequestMethods(HttpMethod.POST)
                // 配置令牌生成器对象
                .tokenServices(tokenService());
    }
    // 注入保存令牌配置的对象
    @Resource
    private TokenStore tokenStore;
    // 添加客户端详情对象(框架提供的对象,不是我们写的)
    @Resource
    private ClientDetailsService clientDetailsService;
    // Spring容器保存令牌生成器对象
    @Bean
    public AuthorizationServerTokenServices tokenService(){
        // 实例化 令牌生成器对象
        DefaultTokenServices services=
                new DefaultTokenServices();
        // 设置令牌保存策略
        services.setTokenStore(tokenStore);
        // 设置令牌有效期(单位是秒,1800就是半小时)
        services.setAccessTokenValiditySeconds(3600);
        // 指定生成令牌的客户端,设置客户端详情
        services.setClientDetailsService(clientDetailsService);
        // 最后返回令牌生成器对象
        return services;
    }

    // 获得加密对象,用于下面方法中的加密操作
    @Resource
    private PasswordEncoder passwordEncoder;

    // 核心配置方法2:配置客户端对应的各种权限
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        // 配置当前授权服务器支持的所有客户端
        // 以及客户端的权限
        // 因为我们现在只有一个<<达内知道>>项目,所以只配置这一个客户端
        // 客户端比较少可以直接保存在内存
        // 如果客户端比较多,可能需要连接数据库获得权限信息
        clients.inMemory()   // 内存中保存客户端信息
                .withClient("knows")    //定义客户端名称
                // 客户端定义的加密密码
                .secret(passwordEncoder.encode("123456"));
    }
}

随笔

postman软件下载地址

https://www.postman.com/downloads/

举报

相关推荐

ProjectDay08

ProjectDay02

ProjectDay20

java 15

15、docker

Day 15

0 条评论