Spring Boot整合oauth2.0搭建统一授权服务(密码模式)

前言

写这个博客得原因是最近想要将自己得api单独发布给第三方使用,但是又不想被别人滥用,所以想弄一个授权服务,但是网上关于oauth2.0的资料层出不穷,看了之后完全不明白应该如果实际的去整合,现在基本成功后记录下来。
关于oauth2.0的概念以及相关的知识等可以建议参阅 理解OAuth 2.0

准备

新建一个Spring Boot的web项目并导入一下依赖:
<dependency>  
    <groupId>org.springframework.security.oauth</groupId>  
    <artifactId>spring-security-oauth2</artifactId>  
</dependency>  
<dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-security</artifactId>  
</dependency>  
<dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-starter-web</artifactId>  
</dependency>  

配置

配置EnableAuthorizationServer

@Configuration  
@EnableAuthorizationServer  
public class OAuth2AuthorizationConfig extends AuthorizationServerConfigurerAdapter {  
  
  
    @Autowired  
    private AuthenticationManager authenticationManager;  
  
    @Autowired  
    private UserDetailsService userService;  
  
    @Autowired  
    private TokenStore tokenStore;  
  
    @Override  
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {  
        clients.inMemory()  
                .withClient("test")//客户端ID  
                .authorizedGrantTypes("password", "refresh_token")//设置验证方式  
                .scopes("read", "write")  
                .secret("123456")  
                .accessTokenValiditySeconds(10000) //token过期时间  
                .refreshTokenValiditySeconds(10000); //refresh过期时间  
    }  
  
    @Override  
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {  
        endpoints.tokenStore(tokenStore)  
                .authenticationManager(authenticationManager)  
                .userDetailsService(userService); //配置userService 这样每次认证的时候会去检验用户是否锁定,有效等  
    }  
  
    @Bean  
    public TokenStore tokenStore() {  
        //使用内存的tokenStore  
        return new InMemoryTokenStore();  
    }  
}

UserService接口定义如下:

public interface UserService extends UserDetailsService {  
    //后期在此新增UserService的业务接口  
}  

其中UserDetailsService只包含一个需要实现的方法,具体实现:

@Primary  
@Service("userService")  
public class UserServiceImpl implements UserService {  
  
    private final static Set<User> users = new HashSet<>();  
  
    static {  
        users.add(new User(1, "test-user1", "123451"));  
        users.add(new User(2, "test-user2", "123452"));  
        users.add(new User(3, "test-user3", "123453"));  
        users.add(new User(4, "test-user4", "123454"));  
    }  
  
    @Override  
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {  
        Optional<User> user = users.stream()  
                .filter((u) -> u.getUserName().equals(s))  
                .findFirst();  
        if (!user.isPresent())  
            throw new UsernameNotFoundException("there's no user founded!");  
        else  
            return UserDetailConverter.convert(user.get());  
    }  
  
    private static class UserDetailConverter {  
        static UserDetails convert(User user) {  
            return new MyUserDetails(user);  
        }  
    }  
}  
根据方法名很容易明白spring 的组件会调用此方法去获取到用户的信息并去验证。
这里的用户信息直接写死的,实际中可以用jdbc或者其他配置等方式。
同时loadUserByUsername方法要求返回一个UserDetails接口:
public interface UserDetails extends Serializable {  
    Collection<? extends GrantedAuthority> getAuthorities();  
  
    String getPassword();  
  
    String getUsername();  
  
    boolean isAccountNonExpired();  
  
    boolean isAccountNonLocked();  
  
    boolean isCredentialsNonExpired();  
  
    boolean isEnabled();  
} 
并且spring已经有了它的一个实现:org.springframework.security.core.userdetails.User类
由于User这个名字很容易和我们项目中的实体User重名这里选择继承这个类自己实现一个UserDetails:
/** 
 * 自定义UserDetails类 携带User实例 
 */  
public class MyUserDetails extends User {  
  
    private com.example.oauth.pojo.User user;  
  
    public MyUserDetails(com.example.oauth.pojo.User user) {  
        super(user.getUserName(), user.getPassword(), true, true, true, true, Collections.EMPTY_SET);  
        this.user = user;  
    }  
  
    public com.example.oauth.pojo.User getUser() {  
        return user;  
    }  
  
    public void setUser(com.example.oauth.pojo.User user) {  
        this.user = user;  
    }  
}  
到此基本的配置就已经完成了,

测试

写一个测试的Controller:

 

@RestController  
public class UserController {  
  
    @Autowired  
    private TokenStore tokenStore;  
  
    @PostMapping("/bar")  
    public String bar(@RequestHeader("Authorization") String auth) {  
  
        MyUserDetails userDetails = (MyUserDetails) tokenStore.readAuthentication(auth.split(" ")[1]).getPrincipal();  
  
        User user = userDetails.getUser();  
  
        return user.getUserName() + ":" + user.getPassword();  
    }  
} 
启动项目:
访问:localhost:8080/bar
返回未授权

访问:localhost:8080/oauth/token获取token
这里的Authrization字段中Basic后面是配置中的clientId + ":" + secret的Base64编码结果
我这里是:test:123456的Base64编码结果
返回token信息:
使用token访问controller:
成功。
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/LightOfMiracle/article/details/79151074

转载于:https://www.cnblogs.com/powerwu/articles/9170473.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值