spring security 單點(diǎn)登錄 簡單實(shí)現(xiàn)
點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號”
優(yōu)質(zhì)文章,第一時間送達(dá)
1、基本概念
SSO(Single Sign On)
SSO英文全稱Single Sign On,單點(diǎn)登錄。SSO是在多個應(yīng)用系統(tǒng)中,用戶只需要登錄一次就可以訪問所有相互信任的應(yīng)用系統(tǒng)。它包括可以將這次主要的登錄映射到其他應(yīng)用中用于同一個用戶的登錄的機(jī)制。它是目前比較流行的企業(yè)業(yè)務(wù)整合的解決方案之一。
spring security
Spring Security 是一個安全框架
Spring Security 提供了若干個可擴(kuò)展的、可聲明式使用的過濾器處理攔截的web請求。
在web請求處理時, Spring Security框架根據(jù)請求url和聲明式配置,篩選出合適的一組過濾器集合攔截處理當(dāng)前的web請求。
這些請求會被轉(zhuǎn)給Spring Security的安全訪問控制框架處理通過之后,請求再轉(zhuǎn)發(fā)應(yīng)用程序處理,從而增強(qiáng)了應(yīng)用的安全性。
Spring Security 提供了可擴(kuò)展的認(rèn)證、鑒權(quán)機(jī)制對Web請求進(jìn)行相應(yīng)對處理。
認(rèn)證:識別并構(gòu)建用戶對象,如:根據(jù)請求中的username,獲取登錄用戶的詳細(xì)信息,判斷用戶狀態(tài),緩存用戶對象到請求上下文等。
決策:判斷用戶能否訪問當(dāng)前請求,如:識別請求url,根據(jù)用戶、權(quán)限和資源(url)的對應(yīng)關(guān)系,判斷用戶能否訪問當(dāng)前請求url。
2、認(rèn)識完了spring security現(xiàn)在就開始擼代碼了
首先我們建一個父工程、三個子工程
sso-demo(父工程)
sso-server(認(rèn)證服務(wù)器)
sso-client1(客戶端1)
sso-client2(客戶端2)
sso-server的pom.xml 中添加依賴
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-jwt</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
配置下服務(wù)器的端口號
server.port = 9999
server.context-path = /server
(一)、新建 SecurityConfig 類并繼承 WebSecurityConfigurerAdapter 添加注解 @Configuration
重寫方法
/**
* 設(shè)置表單登錄等選項(xiàng) --自定義頁面等
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin() //設(shè)置表單登錄
.loginPage("/login")//設(shè)置登錄跳轉(zhuǎn)頁面controller、也可以直接跳轉(zhuǎn)頁面
.loginProcessingUrl("/authentication/form") //自定義登錄頁面的表單提交地址
.and()
.authorizeRequests()
.antMatchers("/login","/register","*/css/**","/code/image","/logout","/code/sms").permitAll()//過濾不需要攔截認(rèn)證的資源
.anyRequest()
.authenticated()
.and()
.csrf().disable();
http.logout().permitAll()
.logoutUrl("/logout")//注銷
.logoutSuccessUrl("/login");//注銷成功后跳轉(zhuǎn)的頁面
}
/**
* 聲明加密的Bean
* @return
*/
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
解決登錄時靜態(tài)資源的url占用saveRequest保存的之前訪問頁面地址,跳轉(zhuǎn)不正確的問題
/**
* 解決靜態(tài)資源被SpringSecurity攔截的問題
* @param web
* @throws Exception
*/
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/static/**");
}
/**
* 指定自定義的userService
* @param auth
* @throws Exception
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
(二)、自定義userService
/**
* 自定義用戶服務(wù)
* Created by zhaoyanzeng on 2019/2/25.
*/
@Component
public class SsoUserDetailService implements UserDetailsService {
@Autowired
private UserDao userDao;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//此處改為數(shù)據(jù)庫
User user = null;
try {
user = userDao.getUserByUsername(username);
} catch (DBException e) {
throw new UsernameNotFoundException("用戶不存在");
}
return user;
}
}
持久層的查詢
@Repository
public class UserDao {
/**
* 保存報(bào)文
* @throws DBException
*/
public User getUserByUsername(String username) throws DBException {
String sql = "select * from user_ where username=?";
Ps ps = new Ps();
ps.add(username);
RMap map = DB.getMap(sql,ps);
//后期完善其他校驗(yàn)信息
return new User(
(String) map.get("username"),
(String) map.get("password"),
AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_USER"));//暫時不考慮角色問題
}
public List<RMap> findUserList() throws DBException {
String sql = "select * from user_";
return DB.getMapList(sql);
}
}
(三)、編寫SsoAuthorizationServerConfig 類 繼承 AuthorizationServerConfigurerAdapter 添加注解
@Configuration
@EnableAuthorizationServer
重寫方法
配置客戶端信息
內(nèi)存存儲客戶端信息
/**
* 覆蓋客戶端配置類
* @param clients
* @throws Exception
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory().
withClient("clinet1")//客戶端ID
.secret("clinet1")//客戶端密碼
.authorizedGrantTypes("authorization_code","refresh_token")//認(rèn)證方式 授權(quán)碼認(rèn)證模式
.scopes("all")
.and()
.withClient("clinet2")
.secret("clinet2")
.authorizedGrantTypes("authorization_code","refresh_token")
.scopes("all");
}數(shù)據(jù)庫存儲客戶端信息
/**
* 配置客戶端詳情服務(wù)(ClientDetailsService)
* 客戶端詳情信息在這里進(jìn)行初始化
* 通過數(shù)據(jù)庫來存儲調(diào)取詳情信息
*
* @param clients clients
* @throws Exception
*/
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.withClientDetails(clientDetails());
}
@Bean
public ClientDetailsService clientDetails() {
JdbcClientDetailsService service = new JdbcClientDetailsService(dataSource);
return service;
}
千萬不要忘了注入dataSource 呀
@Configuration
public class DataSourceConfig {
@Bean(name = "dataSource")
@Qualifier("dataSource")
@ConfigurationProperties(prefix="spring.datasource")
public DataSource getMyDataSource(){
return DataSourceBuilder.create().build();
}
@Bean
public SecurityProperties securityProperties(){
return new SecurityProperties();
}
}
配置文件application.properties中配置數(shù)據(jù)庫的信息
spring.datasource.driver-class-name = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/sso?autoReconnect=true&autoReconnectForPools=true&useUnicode=true&characterEncoding=utf8
spring.datasource.username = root
spring.datasource.password = 123456
接著說SsoAuthorizationServerConfig 重寫的方法
token策略
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(tokenStore())
.accessTokenConverter(jwtAccessTokenConverter());
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(jwtAccessTokenConverter());
}
@Bean
public JwtAccessTokenConverter jwtAccessTokenConverter(){
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("test");
return converter;
}
(四)、編寫頁面
<h2 class="page-header">用戶名密碼登錄</h2>
<div class="row">
<div class="col-md-6">
<div class="panel panel-default">
<div class="panel-body">
<form action="authentication/form" method="post" class="form-horizontal">
<div class="form-group">
<label for="username" class="col-sm-3 control-label">Username</label>
<div class="col-sm-9">
<input type="text" id="username" name="username" value="" placeholder="Type username"
class="form-control"/>
</div>
</div>
<div class="form-group">
<label for="password" class="col-sm-3 control-label">Password</label>
<div class="col-sm-9">
<input type="password" name="password" id="password" value="" placeholder="Type password"
class="form-control"/>
</div>
</div>
<div class="form-group">
<label for="password" class="col-sm-3 control-label">validateCode</label>
<div class="col-sm-9">
<div class="col-sm-8">
<input type="text" name="imageCode" id="imageCode" value="" placeholder="imageCode"
class="form-control"/>
</div>
<div class="col-sm-1">
<img src="code/image?width=200" onclick="this.src='code/image?width=100'"/>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-9">
<input type="submit" value="Login" class="btn btn-primary"/>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
編寫跳轉(zhuǎn)login.html的controller
@Controller
public class LoginController {
@RequestMapping("/login")
public String toLogin() {
return "login";
}
}
認(rèn)證服務(wù)器配置完成,下面看看client需要怎么寫呢
client1
添加依賴 (父子項(xiàng)目可以把依賴放在父工程的pom中,但是實(shí)際項(xiàng)目中可能不會在一起,所以每一個都引了一下)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-jwt</artifactId>
</dependency>
首先在啟動類上添加注解,使之成為一個spring security sso項(xiàng)目
@SpringBootApplication
@RestController
@EnableOAuth2Sso
public class SsoClient2Application {
public static void main(String[] args) {
SpringApplication.run(SsoClient2Application.class, args);
}
@GetMapping("/user")
public Authentication user(Authentication user){
return user;
}
}
添加配置 application.properties
security.oauth2.client.clientId = zhaoyanzeng
security.oauth2.client.clientSecret = ** (自己來定)
security.oauth2.client.user-authorization-uri = http://127.0.0.1:9999/server/oauth/authorize
security.oauth2.client.access-token-uri = http://127.0.0.1:9999/server/oauth/token
security.oauth2.resource.jwt.key-uri = http://127.0.0.1:9999/server/oauth/token_key
server.port = 8070
server.context-path = /client1添加測試頁面 index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>SSO DEMO CLIENT2</h1>
<a href="http://127.0.0.1:8060/client2/index.html">訪問cline2</a>
</body>
</html>
客戶端2可是如此
security.oauth2.client.clientId = zhaoyanzeng
security.oauth2.client.clientSecret = **
security.oauth2.client.user-authorization-uri = http://127.0.0.1:9999/server/oauth/authorize
security.oauth2.client.access-token-uri = http://127.0.0.1:9999/server/oauth/token
security.oauth2.resource.jwt.key-uri = http://127.0.0.1:9999/server/oauth/token_key
server.port = 8060
server.context-path = /client2
client 也添加測試頁面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>SSO DEMO CLIENT2</h1>
<a href="http://127.0.0.1:8070/client1/index.html">訪問cline1</a>
</body>
</html>
(五)、測試
先啟動sso-server 再分別啟動client1 和client2
先訪問http://127.0.0.1:8070/client1/index.html
系統(tǒng)未登錄 跳轉(zhuǎn)認(rèn)證服務(wù)器登錄頁面

登錄完成后跳轉(zhuǎn)回client1/index.html

點(diǎn)擊訪問client2 認(rèn)證后直接跳轉(zhuǎn)client2/index.html

————————————————
版權(quán)聲明:本文為CSDN博主「小增哥」的原創(chuàng)文章,遵循CC 4.0 BY-SA版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:
https://blog.csdn.net/zenggenihao/article/details/88061464
鋒哥最新SpringCloud分布式電商秒殺課程發(fā)布
??????
??長按上方微信二維碼 2 秒
感謝點(diǎn)贊支持下哈 
