spring boot 2.0 許可權進階 spring security + oauth2

最近在學習spring boot 許可權相關模組,網上也有很多關於這方面的教程說明,發現需要搜尋很多資料才能把spring security + oauth2 demoi搭建起來。希望這篇文章能幫助許多正在學習的同學們解決問題。

如果有同學只想整合

spring security

請到我的github 下載程式碼學習:https://github。com/ltztao/test-security

Maven依賴

org。springframework。boot spring-boot-starter-security org。springframework。boot spring-boot-starter-web <!—— https://mvnrepository。com/artifact/org。springframework。security。oauth/spring-security-oauth2 ——> org。springframework。security。oauth spring-security-oauth2 2。3。5。RELEASE

注意:spring-security-oauth2>=2。3。0,<2。3。4中檢測到已知的高嚴重性安全漏洞,請合理引用依賴

認證服務安全配置

/** * 認證伺服器配置 * @author ltzhang * @time 2019-11-28 */ @Configuration @EnableAuthorizationServer public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter { /** * 注入許可權驗證控制器 來支援 password grant type */ @Autowired private AuthenticationManager authenticationManager; /** * 注入userDetailsService,開啟refresh_token需要用到 */ @Autowired private MyUserDetailsService userDetailsService; /** * 資料來源 */ @Autowired private DataSource dataSource; @Autowired private RedisConnectionFactory connectionFactory; @Autowired private MyOAuth2WebResponseExceptionTranslator webResponseExceptionTranslator; @Bean public TokenStore tokenStore() { return new RedisTokenStore( connectionFactory ); } @Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { security。tokenKeyAccess(“permitAll()”) 。checkTokenAccess(“permitAll()”) 。allowFormAuthenticationForClients(); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients。jdbc(dataSource); } @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { //開啟密碼授權型別 endpoints。authenticationManager(authenticationManager); //配置token儲存方式 endpoints。tokenStore(tokenStore()); //自定義登入或者鑑權失敗時的返回資訊 endpoints。exceptionTranslator(webResponseExceptionTranslator); //要使用refresh_token的話,需要額外配置userDetailsService endpoints。userDetailsService( userDetailsService ); endpoints。allowedTokenEndpointRequestMethods(HttpMethod。GET, HttpMethod。POST); } }

此處token資訊都存放在redis中,client資訊存放在資料庫中(如果要配置在記憶體中,請自行百度)大家如果想講token資訊儲存在資料請自行做相關修改,oauth2 相關資料表https://github。com/ltztao/spring-security-oauth2/blob/master/init-oauth2。sql

—— 由於當前token存放在redis中沒使用jdbc且只有令牌存放在資料庫中達到可管理,故只要建立oauth_client_details即可 —— 如若token存放資料庫中則需要建立以下所有表 CREATE TABLE `oauth_client_details` ( `client_id` varchar(128) NOT NULL, `resource_ids` varchar(256) DEFAULT NULL, `client_secret` varchar(256) DEFAULT NULL, `scope` varchar(256) DEFAULT NULL, `authorized_grant_types` varchar(256) DEFAULT NULL, `web_server_redirect_uri` varchar(256) DEFAULT NULL, `authorities` varchar(256) DEFAULT NULL, `access_token_validity` int(11) DEFAULT NULL, `refresh_token_validity` int(11) DEFAULT NULL, `additional_information` varchar(4096) DEFAULT NULL, `autoapprove` varchar(256) DEFAULT NULL, PRIMARY KEY (`client_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 資料庫欄位說明 http://andaily。com/spring-oauth-server/db_table_description。html

資源服務配置

/** * 資源提供端的配置 * @author ltzhang * @time 2019-11-28 */ @Configuration @EnableResourceServer public class ResourceServerConfig extends ResourceServerConfigurerAdapter { @Autowired private RestAuthAccessDeniedHandler deniedHandler; @Autowired private MyAuthenticationEntryPoint authenticationEntryPoint; /** * 這裡設定需要token驗證的url * 可以在WebSecurityConfigurerAdapter中排除掉, * 對於相同的url,如果二者都配置了驗證 * 則優先進入ResourceServerConfigurerAdapter,進行token驗證。而不會進行 * WebSecurityConfigurerAdapter 的 basic auth或表單認證。 */ @Override public void configure(HttpSecurity http) throws Exception { http。requestMatchers()。antMatchers(“/hi”) 。and() 。authorizeRequests() 。antMatchers(“/hi”) 。authenticated(); //需要的時候建立session,支援從session中獲取認證資訊,ResourceServerConfiguration中 //session建立策略是stateless不使用,這裡其覆蓋配置可建立session http。sessionManagement()。sessionCreationPolicy(SessionCreationPolicy。IF_REQUIRED); } @Override public void configure(ResourceServerSecurityConfigurer resources) { resources。authenticationEntryPoint(authenticationEntryPoint) 。accessDeniedHandler(deniedHandler); //此處是關鍵,預設stateless=true,只支援access_token形式, // OAuth2客戶端連線需要使用session,所以需要設定成false以支援session授權 resources。stateless(false); } }

Web安全配置

@Configuration @EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true) public class BrowerSecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private MyAuthenticationSuccessHandler successHandler; @Autowired private MyAuthenticationFailHandler failHandler; @Autowired private AjaxSessionInformationExpiredStrategy expiredStrategy; @Autowired private SecurityAuthenticationProvider provider; @Autowired private RestAuthAccessDeniedHandler deniedHandler; @Autowired private MyLogoutSuccessHandler logoutSuccessHandler; @Autowired private MyAuthenticationEntryPoint entryPoint; /** * 如若需從資料庫動態判斷許可權則實現 AccessDecisionManager * @param http * @throws Exception */ @Override protected void configure(HttpSecurity http) throws Exception { http。authorizeRequests() //“/login”不進行許可權驗證 。antMatchers(“/login”)。permitAll() // 。antMatchers(“/favicon。ico”)。permitAll() 。and() 。authorizeRequests() 。anyRequest()。authenticated() //其他的需要登陸後才能訪問 。and() 。formLogin() //loginProcessingUrl用於指定前後端分離的時候呼叫後臺登入介面的名稱 。loginProcessingUrl(“/login”) 。usernameParameter(“username”) 。passwordParameter(“password”) 。successHandler(successHandler) 。failureHandler(failHandler)。permitAll() 。and() //loginProcessingUrl用於指定前後端分離的時候呼叫後臺登出介面的名稱 。logout()。logoutUrl(“/logout”) 。invalidateHttpSession(true) 。logoutSuccessHandler(logoutSuccessHandler) 。and() //配置沒有許可權的自定義處理類 。exceptionHandling() 。accessDeniedHandler(deniedHandler) 。authenticationEntryPoint(entryPoint); // 自定義處理未登入 // 設定跨域問題 http。cors()。and()。csrf()。disable(); http。sessionManagement() 。maximumSessions(1) // 同一個賬號只能在一個地方登陸 。expiredSessionStrategy(expiredStrategy); } /** * 自定義驗證邏輯 * @param auth * @throws Exception */ @Override protected void configure(AuthenticationManagerBuilder auth){ auth。authenticationProvider(provider); } @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception{ return super。authenticationManager(); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }

當前demo中如:token過期,登入失敗,登入成功。。。都處理返回json,如果其它需求請自行處理。

測試image。png

完整的程式碼下載連結:https://github。com/ltztao/spring-security-oauth2

參考資料均來自網上