SpringCloud OAuth2 + JWT 认证授权(一)授权服务器

系列文章

Spring Cloud oAuth2(一)搭建授权服务器以及访问

Spring Cloud oAuth2(二)搭建资源服务器以及测试

SpringCloud OAuth2 + JWT 认证授权(一)授权服务器

SpringCloud OAuth2 + JWT 认证授权(二)资源服务器

目录

简介

实体对象

授权配置

结尾


简介

这里对个人在搭建第三方授权服务的过程中,遇到的问题进行总结。如果不是非必要的第三方登录,单个JWT就能满足简单的授权验证的,不过相关的验证和授权需要自己去写。本文源码:源码地址。

实体对象

  • 角色
@Data
@Entity
public class Role implements GrantedAuthority, Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false,unique = true)
    private String name;

    @Override
    public String getAuthority() {
        return name;
    }
}
  • 用户以及和角色的对应关系
@Data
@Entity
public class User implements UserDetails, Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false,unique = true)
    private String username;

    private String password;

    @ManyToMany(cascade = CascadeType.ALL,fetch = FetchType.EAGER)
    @JoinTable(
            name = "user_role",
            joinColumns = {@JoinColumn(name = "user_id",referencedColumnName = "id")},
            inverseJoinColumns = {@JoinColumn(name="role_id",referencedColumnName = "id")}
    )
    List authorities;

    @Override
    public Collection getAuthorities() {
        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;
    }

注意:对象相关的角色信息一定要返回(authorities),这里本人写快了返回null。。。。

授权配置

  • 实现简单的查询接口
public interface UserDao extends JpaRepository {

    User findUserByUsername(String username);
}
  • 实现UserDetailsService并重写loadUserByUsername方法
@Service
public class UserService implements UserDetailsService {

    @Autowired
    private UserDao userDao;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        return userDao.findUserByUsername(username);
    }
}
  • 重写spring security相关配置,配置授权验证方式等
@Configuration
@EnableWebSecurity
public class WebSecurityConfig  extends WebSecurityConfigurerAdapter {


    @Autowired
    private UserService userService;


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


    //相关http安全配置,异常处理和相关资源以及用户授权配置
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .exceptionHandling()
            .authenticationEntryPoint((request,response,authException)->response.sendError(HttpServletResponse.SC_UNAUTHORIZED))
            .and()
            .authorizeRequests()
            .anyRequest()
            .authenticated()
            .and()
            .httpBasic();
    }

    //用户读取位置以及密码验证方式
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .userDetailsService(userService)
            .passwordEncoder(passwordEncoder());
    }


    //开启密码验证
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}
  • 授权服务器授权配置
@Configuration
@EnableAuthorizationServer
public class AuthServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    @Qualifier("authenticationManagerBean")
    public AuthenticationManager authenticationManager;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients
                .inMemory()
                .withClient("kevin")
                .secret(passwordEncoder.encode("kevin12345"))
                .scopes("client")
                .authorizedGrantTypes("password","refresh_token")
                .accessTokenValiditySeconds(3600);
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints
                //存储策略
                .tokenStore(new JwtTokenStore(jwtTokenEnhancer()))
                //增强策略
                .tokenEnhancer(jwtTokenEnhancer())
                //开启密码授权验证
                .authenticationManager(authenticationManager);
    }



    //jwt身份转换器,用于将封装在jwt里面的信息解析或者转换
    public JwtAccessTokenConverter jwtTokenEnhancer()
    {
        //RSA非对称加密密钥工厂,参数一为密钥地址,参数二为打开密钥的密码
        KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(new ClassPathResource("auth-jwt.jks"),"jwt12345".toCharArray());
        JwtAccessTokenConverter converter =  new JwtAccessTokenConverter();
        converter.setKeyPair(keyStoreKeyFactory.getKeyPair("auth-jwt","jwt12345".toCharArray()));
        return converter;
    }

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        security
                .tokenKeyAccess("permitAll()")
                .checkTokenAccess("permitAll()")
                .allowFormAuthenticationForClients();
    }

注意:

  1. 这里的查看密钥storepass和生成密钥keypass是一样的,相关的RSA私钥和公钥生成博客有很多
  2. 要用openssl导出公钥命令的必须下载安装openssl服务
  3. 公钥导出可以直接复制显示的publickey(不用缩成一行!)并提取成文件(文中是这样的),也可以写程序去获取

结尾

这里仅仅是简单的demo,生产用还有很多不足的地方,比如退出token失效等。

你可能感兴趣的:(SpringCloud)