美文网首页程序员
利用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