美文网首页程序员
利用Spring Security OAuth2 进行API权限

利用Spring Security OAuth2 进行API权限

作者: AlienJunX | 来源:发表于2017-10-19 16:24 被阅读1085次

客户端在访问API时候需要经过权限控制,方便在服务端进行控制引入了Spring Security OAuth2 。
客户端必须得到用户的授权(authorization grant),才能获得令牌(access token)。OAuth 2.0定义了四种授权方式。

  • 授权码模式(authorization code)
  • 简化模式(implicit)
  • 密码模式(resource owner password credentials)
  • 客户端模式(client credentials)
自有项目采用客户端模式进行授权

客户端通过密码和服务端注册的client_id、client_secret、grant_type进行授权,直接获取token,而不需要提示用户是否同意授权。授权后token和用户、客户端是绑定的,通过token可以拿到用户也可以知道用户客户端来源

客户端授权.jpg

服务端配置security配置

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    PathLoginAuthenticationEntryPoint loginEntryPoint;

    @Autowired
    PathUrlAuthenticationFailureHandler loginFailureHandler;

    @Autowired
    PathUrlLogoutSuccessHandler logoutSuccessHandler;

    @Override
    @Bean
    public UserDetailsService userDetailsService() {
        return new LoginUserDetailsService();
    }

    @Bean
    public PathTokens pathTokens() {
        return new PathTokens(Arrays.asList("user", "admin", "partner"));
    }

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

    @Bean
    CacheManager cacheManager() {
        SimpleCacheManager cacheManager = new SimpleCacheManager();
        cacheManager.setCaches(Arrays.asList(new GuavaCache(CommonConstant.WECHAT_CODE,
                CacheBuilder.newBuilder().expireAfterAccess(5, TimeUnit.MINUTES).build())));
        return cacheManager;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth)
            throws Exception {
        auth.userDetailsService(userDetailsService()).passwordEncoder(passwordEncoder());
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/js/**", "/css/**", "/images/**", "/fonts/**" , "/upload/**", "/MP*.txt");
    }

    // 注意将/oauth/*路径开放
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable();
        http.authorizeRequests()
                .antMatchers("/login", "/resetpwd", "/sendsms", "/common/**","/register","/oauth/**").permitAll()
                .antMatchers("/user/**").hasAuthority(User.Role.USER.toString())
                .antMatchers("/admin/**").hasAuthority(User.Role.ADMIN.toString())
                .anyRequest().authenticated();
        http.formLogin().loginProcessingUrl("/login")
                .usernameParameter("username").passwordParameter("password")
                .defaultSuccessUrl("/default", true)
                .failureHandler(loginFailureHandler);
        http.logout()
                .logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
                .deleteCookies("remember-me")
                .invalidateHttpSession(true)
                .logoutSuccessHandler(logoutSuccessHandler);
        http.rememberMe()
                .tokenValiditySeconds(604800);
        http.exceptionHandling().authenticationEntryPoint(loginEntryPoint);
    }

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

}

oauth2配置

@Configuration
public class OAuth2Config {

    private static final String RESOURCE_ID = "restservice";

    @Configuration
    @EnableResourceServer
    protected static class ResourceServerConfiguration extends
            ResourceServerConfigurerAdapter {

        @Override
        public void configure(ResourceServerSecurityConfigurer resources) {
            resources
                    .resourceId(RESOURCE_ID);
        }

        @Override
        public void configure(HttpSecurity http) throws Exception {
            http.requestMatchers().antMatchers("/api/**")
                    .and()
                    .authorizeRequests()
                    .antMatchers("/api/**").authenticated();
        }
    }

    @Configuration
    @EnableAuthorizationServer
    protected static class AuthorizationServerConfiguration extends
            AuthorizationServerConfigurerAdapter {

        private TokenStore tokenStore = new InMemoryTokenStore();

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

        @Autowired
        private LoginUserDetailsService loginUserDetailsService;

        @Override
        public void configure(AuthorizationServerEndpointsConfigurer endpoints)
                throws Exception {
            endpoints
                    .tokenStore(this.tokenStore)
                    .authenticationManager(this.authenticationManager)
                    .userDetailsService(loginUserDetailsService);
        }

        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients
                    .inMemory()
                    .withClient("clientapp")
                    .authorizedGrantTypes("password", "refresh_token")
                    .scopes("read", "write")
                    .resourceIds(RESOURCE_ID)
                    .secret("123456");
        }

        @Bean
        @Primary
        public DefaultTokenServices tokenServices() {
            DefaultTokenServices tokenServices = new DefaultTokenServices();
            tokenServices.setSupportRefreshToken(true);
            tokenServices.setTokenStore(this.tokenStore);
            return tokenServices;
        }

        @Override
        public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
            // 允许对客户端进行表单身份验证
            oauthServer.allowFormAuthenticationForClients();
        }
    }

}

测试:

http://localhost:9090/oauth/token
grant_type:password
client_id:clientapp
client_secret:123456
scope:read write
username:admin
password:000000

得到token:

{"access_token":"f8e1509f-f7a3-40fc-ac8a-4815852c47e3","token_type":"bearer","refresh_token":"4ae758f1-d9a3-40c4-8d76-3bb57a4ae7d9","expires_in":42476,"scope":"read write"}

使用token进行api请求:

http://localhost:9090/api/test?access_token=4730a768-3176-475a-91bb-a6d299b8f198

参考资料:
http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html
http://www.dannysite.com/blog/181/
http://www.cnblogs.com/lexiaofei/p/7152326.html?utm_source=itdadao&utm_medium=referral
http://www.cnblogs.com/xingxueliao/p/5911292.html

相关文章

网友评论

    本文标题:利用Spring Security OAuth2 进行API权限

    本文链接:https://www.haomeiwen.com/subject/lbnuuxtx.html