springsecurity+oauth2.0 分布式认证授权案例-uaa服务配置2

OAuth2.0授权服务配置详解

一 uaa认证服务配置

1.1 EnableAuthorizationServer的作用

1.1.1 作用说明

1.EnableAuthorizationServer可以用@EnableAuthorizationServer注解,并继承AuthorizationServerConfigurerAdapter来配置oauth2.0授权服务器

2.需要在config目录下进行操作:

1.1.2 核心配置内容(*重要) 

 3.AuthorizationServerConfigurerAdapter要求配置以下几个类,这几个类是由Spring创建的独立的配置对象,它们会被Spring传入AuthorizationServerConfigurer中进行配置。

public class AuthorizationServerConfigurerAdapter implements AuthorizationServerConfigurer {
public AuthorizationServerConfigurerAdapter() {}
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {}
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {}
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {}
}
1.ClientDetailsServiceConfigurer用来配置客户端详情服务(ClientDetailsService),客户端详情信息在 这里进行初始化,你能够把客户端详情信息写死在这里或者是通过数据库来存储调取详情信息。
2.AuthorizationServerEndpointsConfigurer用来配置令牌(token)的访问端点和令牌服务(token  services)。
3.AuthorizationServerSecurityConfigurer用来配置令牌端点的安全约束

1.2 配置ClientDetailsServiceConfigurer客户端详情信息

1.2.1 clientDetailsServiceConfigurer配置说明

ClientDetailsServiceConfigurer 能够使用内存或者JDBC来实现客户端详情服,ClientDetailsService)务,ClientDetailsService负责查找ClientDetails,而ClientDetails有几个重要的属性如下列表:
clientId:(必须的)用来标识客户的Id。
secret:(需要值得信任的客户端)客户端安全码,如果有的话。
scope用来限制客户端的访问范围,如果为空(默认)的话,那么客户端拥有全部的访问范围
authorizedGrantTypes:此客户端可以使用的授权类型,默认为空。
authorities此客户端可以使用的权限(基于Spring Security authorities)。
总结:客户端详情,能够在应用程序运行的时候进行更新,可以通过访问底层的存储服务(例如将客户端详情存储在一个关系数据库的表中,就可以使用JdbcClientDetailsService)或者通过自己实现ClientRegistrationService接口同时你也可以实现 ClientDetailsService 接口)来进行管理。

1.2.2 案例代码

使用内存案例:

1.3  AuthorizationServerTokenServices管理令牌的配置

1.3.1 令牌的配置

AuthorizationServerTokenServices 接口定义了一些操,作使得你可以对令牌进行一些必要的管理,令牌可以被用来 加载身份信息,里面包含了这个令牌的相关权限
1.自己可以创建 AuthorizationServerTokenServices 这个接口的实现,则需要继承 DefaultTokenServices 这个类,里面包含了一些有用实现,你可以使用它来修改令牌的格式和令牌的存储。
2.默认的,当它尝试创建一个令牌的时候,是使用随机值来进行填充的,除了持久化令牌是委托一个 TokenStore 接口来实现以外,这个类几乎帮你做了所有的事情。
3.TokenStore 这个接口有一个默认的实现,它就是 InMemoryTokenStore
4.下面有几个版本,它们都实现了TokenStore接口:

1.InMemoryTokenStore:这个版本的实现是被默认采用的,它可以完美的工作在单服务器上(即访问并发量压力不大的情况下,并且它在失败的时候不会进行备份),大多数的项目都可以使用这个版本的实现来进行尝试,你可以在开发的时候使用它来进行管理,因为不会被保存到磁盘中,所以更易于调试。
2.JdbcTokenStore:这是一个基于JDBC的实现版本,令牌会被保存进关系型数据库。使用这个版本的实现时,你可以在不同的服务器之间共享令牌信息,使用这个版本的时候请注意把"spring-jdbc"这个依赖加入到你的classpath当中。
3.JwtTokenStore:这个版本的全称是 JSON Web Token(JWT),它可以把令牌相关的数据进行编码(因此对于后端服务来说,它不需要进行存储,这将是一个重大优势),但是它有一个缺点,那就是撤销一个已经授权令牌将会非常困难,所以它通常用来处理一个生命周期较短的令牌以及撤销刷新令牌(refresh_token)。另外一个缺点就是这个令牌占用的空间会比较大,如果你加入了比较多用户凭证信息JwtTokenStore 不会保存任何数据,但是它在转换令牌值以及授权信息方面与 DefaultTokenServices 所扮演的角色是一样的

 1.3.2 配置截图

 1.3.3 代码配置

1.定义TokenConfifig
confifig包下定义TokenConfig,我们暂时先使用InMemoryTokenStore,生成一个普通的令牌。
@Configuration
 public class TokenConfig { 
@Bean 
public TokenStore tokenStore() { 
return new InMemoryTokenStore();
 } 
}
2. 在AuthorizationServer中定义AuthorizationServerTokenServices

 3.代码如下

@Autowired 
private TokenStore tokenStore;
 @Autowired 
private ClientDetailsService clientDetailsService; 
@Bean 
public AuthorizationServerTokenServices tokenService() { 

DefaultTokenServices service=new DefaultTokenServices(); 

service.setClientDetailsService(clientDetailsService); 

service.setSupportRefreshToken(true); service.setTokenStore(tokenStore); 

service.setAccessTokenValiditySeconds(7200); // 令牌默认有效期2小时 

service.setRefreshTokenValiditySeconds(259200); // 刷新令牌默认有效期3天

 return service;
 }

1.4  AuthorizationServerEndpointsConfigurer 令牌访问端点配置

 AuthorizationServerEndpointsConfigurer 这个对象的实例可以完成令牌服务以及令牌endpoint配置。

1.4.1 配置授权类型(Grant Types

AuthorizationServerEndpointsConfigurer 通过设定以下属性决定支持的授权类型(Grant Types:

1.4.2 配置授权端点的URLEndpoint URLs

AuthorizationServerEndpointsConfigurer 这个配置对象有一个叫做 pathMapping() 的方法用来配置端点URL
接,它有两个参数:
第一个参数:String 类型的,这个端点URL的默认链接。
第二个参数:String 类型的,你要进行替代的URL链接。
以上的参数都将以 "/" 字符为开始的字符串,框架的默认URL链接如下列表,可以作为这个 pathMapping() 方法的 第一个参数:

 1.4.3 代码的实现

AuthorizationServer类中配置令牌访问端点

 1.5  令牌端点的安全约束

AuthorizationServerSecurityConfigurer用来配置令牌端点(Token Endpoint)的安全约束,在 AuthorizationServer中配置如下:

1.tokenkey这个endpoint,当使用JwtToken且使用非对称加密时,资源服务用于获取公钥而开放的,这里指这个 endpoint完全公开。
2.checkToken这个endpoint完全公开
3.允许表单认

1.6 授权服务配置总结

授权服务配置分成三大块,可以关联记忆。
1.既然要完成认证,它首先得知道客户端信息从哪儿读取,因此要进行客户端详情配置。
2.既然要颁发token,那必须得定义token的相关endpoint,以及token如何存取,以及客户端支持哪些类型的 token。
3.既然暴露除了一些endpoint,那对这些endpoint可以定义一些安全上的约束

1.7 web安全配置

1.在config目录下,新建WebSecurityconfig的配置

2.截图:

3.代码如下

@Configuration
 @EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)
 public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 
   @Bean 
public PasswordEncoder passwordEncoder() { 
return new BCryptPasswordEncoder(); 
}
  @Bean 
public AuthenticationManager authenticationManagerBean() throws Exception { 
return super.authenticationManagerBean(); 
}

@Configuration @EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

@Bean 
public PasswordEncoder passwordEncoder() { 
return new BCryptPasswordEncoder(); 
}

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

//安全拦截机制(最重要) 
@Override 
protected void configure(HttpSecurity http) throws Exception {
 http.csrf().disable() 
.authorizeRequests() 
.antMatchers("/r/r1").hasAnyAuthority("p1") 
.antMatchers("/login*").permitAll() 
.anyRequest().authenticated() 
.and() .formLogin() ; 
} 
}

二 配置详细流程

2.1 配置 SpringDataUserDetailsService

2.1.1 pom文件

pom文件新增这个两个依赖

  <!-- 分页插件 -->
    <dependency>
      <groupId>com.github.pagehelper</groupId>
      <artifactId>pagehelper-spring-boot-starter</artifactId>
      <version>1.2.5</version>
    </dependency>
    <!-- alibaba的druid数据库连接池 -->
    <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>druid-spring-boot-starter</artifactId>
      <version>1.1.9</version>
    </dependency>

2.1.2 application文件

2.1.3 mapper文件

 2.1.4 dao接口

package com.ljf.springsecurity.oauth.dao;

import com.ljf.springsecurity.oauth.model.PermissionDto;
import com.ljf.springsecurity.oauth.model.UserDto;

import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface UserMapper {
    //查找用户名
    public UserDto getUserByUsername(@Param("userName") String username);
    //查找该用户名下的权限
    public List<PermissionDto> findPermissionsByUserId(@Param("userId") String userId);
}

 2.1.5 model

1.UserDto

package com.ljf.springsecurity.oauth.model;

import lombok.Data;

/**
 * @author Administrator
 * @version 1.0
 **/
@Data
public class UserDto {
    private String id;
    private String username;
    private String password;
    private String fullname;
    private String mobile;
}

2.PermissionDto

/**
 * @author Administrator
 * @version 1.0
 **/
@Data
public class PermissionDto {

    private String id;
    private String code;
    private String description;
    private String url;
}

 2.1.6  SpringDataUserDetailsService

package com.ljf.springsecurity.oauth.service;

import com.ljf.springsecurity.oauth.dao.UserMapper;
import com.ljf.springsecurity.oauth.model.PermissionDto;
import com.ljf.springsecurity.oauth.model.UserDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * @ClassName: SpringDataUserDetailsService
 * @Description: TODO
 * @Author: liujianfu
 * @Date: 2021/08/14 09:44:20 
 * @Version: V1.0
 **/
@Service
public class SpringDataUserDetailsService implements UserDetailsService {
    @Autowired
    private UserMapper userMapper;
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        //将来连接数据库根据账号查询用户信息
        UserDto userDto = userMapper.getUserByUsername(username);
        if(userDto == null){
            //如果用户查不到,返回null,由provider来抛出异常
            return null;


        }
        //权限
       // String [] authoritys={"p1"};
        //根据用户的id查询用户的权限
        List<PermissionDto> permissionsList =  userMapper.findPermissionsByUserId(userDto.getId());
        List<String> permissions = new ArrayList<>();
        permissionsList.forEach(c -> permissions.add(c.getCode()));
        //将permissions转成数组
        String[] permissionArray = new String[permissions.size()];
        permissions.toArray(permissionArray);
        UserDetails userDetails = User.withUsername(userDto.getUsername()).password(userDto.getPassword()).authorities(permissionArray).build();
        return userDetails;
    }
}

  2.1.7  启动类

package com.ljf.springsecurity.oauth;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.openfeign.EnableFeignClients;

/**
 * Hello world!
 *
 */
@SpringBootApplication
@EnableDiscoveryClient
@EnableHystrix
@EnableFeignClients(basePackages = {"com.ljf.springsecurity.oauth"})
@MapperScan("com.ljf.springsecurity.oauth.dao") //@MapperScan 用户扫描MyBatis的Mapper
public class UaaApp
{
    public static void main( String[] args )
    {
        SpringApplication.run( UaaApp.class, args);
    }
}

2.2 编写AuthorizationServer

创建一个配置文件AuthorizationServer,编写客户端信息

2.2.1 客户端信息

代码案例:

    //step1:客户端详情服务
    @Override
    public void configure(ClientDetailsServiceConfigurer clients)
            throws Exception {
     clients.inMemory()// 使用in-memory存储
                .withClient("c1")// client_id
                .secret(new BCryptPasswordEncoder().encode("secret"))//客户端密钥
                .resourceIds("res1")//资源列表
                .authorizedGrantTypes("authorization_code", "password","client_credentials","implicit","refresh_token")// 该client允许的授权类型authorization_code,password,refresh_token,implicit,client_credentials
                .scopes("all")// 允许的授权范围
                .autoApprove(false)//false跳转到授权页面
                //加上验证回调地址
                .redirectUris("http://www.baidu.com");
    }

2.2.2 编写令牌管理服务

1.编写tokenconfig

 2.在AuthorizationServer中配置令牌服务

 2.2.4 编写令牌的端点

1.编写存储

 2.编写端点

编写一个:WebSecurityConfig:在这里注册认证管理器

 3.在AuthorizationServer文件中引用

  2.2.5 编写令牌的约束

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值