1、使用springsecurity普通登錄 https://mrbird.cc/Spring-Security-Authentication.html
1-1、Spring Security的核心思想是用戶授權和資源認證。
- 資源認證:認證訪問系統的用戶,是調用authenticationManager.authenticate()方法來獲得證書authentication,一般我們採用用戶名、密碼方式認證,那麼authentication的實現類就是UsernamePasswordAuthentication。
- 用戶授權:是讓用戶可以訪問哪些資源,一般在WebSecurityConfigurerApdater的繼承類中編寫。
1-2、userService:用戶和密碼是否準確可以寫到裏邊去。
package cc.mrbird.security.browser;
import cc.mrbird.domain.MyUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class UserDetailService implements UserDetailsService {
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
System.out.println("username :"+username);
// 模擬一個用戶,替代數據庫獲取邏輯
MyUser user = new MyUser();
user.setUserName(username);
user.setPassword(this.passwordEncoder.encode("123456"));
// 輸出加密後的密碼
System.out.println(user.getPassword());
return new User(username, user.getPassword(), user.isEnabled(),
user.isAccountNonExpired(), user.isCredentialsNonExpired(),
user.isAccountNonLocked(), AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));
}
}
package cc.mrbird.security.browser;
import cc.mrbird.handler.MyAuthenticationFailureHandler;
import cc.mrbird.handler.MyAuthenticationSucessHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class BrowserSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private MyAuthenticationSucessHandler authenticationSucessHandler;
@Autowired
private MyAuthenticationFailureHandler authenticationFailureHandler;
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin() // 表單登錄
// http.httpBasic() // HTTP Basic
.loginPage("/authentication/require") // 登錄跳轉 URL
.loginProcessingUrl("/login") // 處理表單登錄 URL
.successHandler(authenticationSucessHandler) // 處理登錄成功
.failureHandler(authenticationFailureHandler) // 處理登錄失敗
.and()
.authorizeRequests() // 授權配置
.antMatchers("/authentication/require", "/login.html").permitAll() // 登錄跳轉 URL 無需認證
.anyRequest() // 所有請求
.authenticated() // 都需要認證
.and().csrf().disable();
}
}
2-1、單點登錄授權模式選擇授權碼模式。
2、Client(客戶端)
客戶端配置(必須與oauth服務配置一致)
security.oauth2.client.client-id
指定OAuth2 client ID
security.oauth2.client.client-secret
指定OAuth2 client secret. 默認是一個隨機的secret
security.oauth2.client.user-authorization-uri
用戶跳轉去獲取access token的URI
security.oauth2.client.access-token-uri
指定獲取access token的URI
security.oauth2.resource.jwt.key-uri
JWT token的URI. 當key爲公鑰時,或者value不指定時指定
2、AuthorizationServer ( 服務中心 )
2-1、AuthorizationServerConfigurerAdapter
package cc.mrbird.sso.server.config;
import cc.mrbird.sso.server.service.UserDetailService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
/**
* @author MrBird
*/
@Configuration
@EnableAuthorizationServer
public class SsoAuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private PasswordEncoder passwordEncoder;
@Autowired
private UserDetailService userDetailService;
@Bean
public TokenStore jwtTokenStore() {
return new JwtTokenStore(jwtAccessTokenConverter());
}
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter() {
JwtAccessTokenConverter accessTokenConverter = new JwtAccessTokenConverter();
accessTokenConverter.setSigningKey("test_key");//祕鑰
return accessTokenConverter;
}
//Client和AuthorizationServer配置一致
// clients.inMemory()
// .withClient("app-a") //與客戶端配置security.oauth2.client.client-id一致
// .secret(passwordEncoder.encode("app-a-1234")) //與客戶端security.oauth2.client.client-secret配置一致
// .authorizedGrantTypes("refresh_token","authorization_code") //刷新授權碼,必須這樣寫
// .accessTokenValiditySeconds(3600) //授權碼有效時間,時間越短越安全
// .scopes("all") //允許授權範圍
// .autoApprove(true)
// .redirectUris("http://127.0.0.1:9090/app1/login") //登錄地址(本案例採用默認登錄地址,可以自己配)
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("app-a")
.secret(passwordEncoder.encode("app-a-1234"))
.authorizedGrantTypes("refresh_token","authorization_code")
.accessTokenValiditySeconds(3600)
.scopes("all")
.autoApprove(true)
.redirectUris("http://127.0.0.1:9090/app1/login")
.and()
.withClient("app-b")
.secret(passwordEncoder.encode("app-b-1234"))
.authorizedGrantTypes("refresh_token","authorization_code")
.accessTokenValiditySeconds(7200)
.scopes("all")
.autoApprove(true)
.redirectUris("http://127.0.0.1:9091/app2/login");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.tokenStore(jwtTokenStore())
.accessTokenConverter(jwtAccessTokenConverter())
.userDetailsService(userDetailService);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) {
security.tokenKeyAccess("isAuthenticated()"); // 獲取密鑰需要身份認證
}
}
2-2、WebSecurityConfigurerAdapter :spring security的默認http配置,可以配置HttpSecurity,包括formLogin,antMatcher,hasRole ,本案例不考慮太多
package cc.mrbird.sso.server.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
* @author MrBird
*/
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin() //表單登錄
.and()
.authorizeRequests()
.anyRequest()
.authenticated();//所有請求必須在登錄後纔可以訪問
}
}