<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          spring security 單點(diǎn)登錄 簡單實(shí)現(xiàn)

          共 24019字,需瀏覽 49分鐘

           ·

          2021-03-18 09:41

          點(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)贊支持下哈 

          瀏覽 114
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  人人爱人人看人人搞 | 蜜桃91在线观看 | 国产内射免费视频 | 午夜福利电影在线免费观看 | 日本一区视频免费 |