国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

服務(wù)器之家:專(zhuān)注于服務(wù)器技術(shù)及軟件下載分享
分類(lèi)導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語(yǔ)言|JavaScript|易語(yǔ)言|vb.net|

服務(wù)器之家 - 編程語(yǔ)言 - Java教程 - Java spring單點(diǎn)登錄系統(tǒng)

Java spring單點(diǎn)登錄系統(tǒng)

2021-12-20 13:33良哥 666 、攀哥 666 Java教程

這篇文章主要介紹了Java spring單點(diǎn)登錄系統(tǒng),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

1.單點(diǎn)登錄系統(tǒng)介紹

多點(diǎn)登陸系統(tǒng)。應(yīng)用起來(lái)相對(duì)繁瑣(每次訪(fǎng)問(wèn)資源服務(wù)都需要重新登陸認(rèn)證和授權(quán))。與此同時(shí),系統(tǒng)代碼的重復(fù)也比較高。所以單點(diǎn)登錄系統(tǒng),倍受歡迎!
單點(diǎn)登錄系統(tǒng),即多個(gè)站點(diǎn)共用一臺(tái)認(rèn)證授權(quán)服務(wù)器,用戶(hù)在其中任何一個(gè)站點(diǎn)登錄后,可以免登錄訪(fǎng)問(wèn)其他所有站點(diǎn)。而且,各站點(diǎn)間可以通過(guò)該登錄狀態(tài)直接交互。

Java spring單點(diǎn)登錄系統(tǒng)

 

2.簡(jiǎn)單業(yè)務(wù)實(shí)現(xiàn)

在文件上傳的項(xiàng)目添加認(rèn)證授權(quán)服務(wù),義登錄頁(yè)面(login.html),然后在頁(yè)面中輸入自己的登陸賬號(hào),登陸密碼,將請(qǐng)求提交給網(wǎng)關(guān),然后網(wǎng)關(guān)將請(qǐng)求轉(zhuǎn)發(fā)到auth工程,登陸成功和失敗要返回json數(shù)據(jù),按照如下結(jié)構(gòu)實(shí)現(xiàn)

Java spring單點(diǎn)登錄系統(tǒng)

在02-sca工程創(chuàng)建 sca-auth子module,作為認(rèn)證授權(quán)服務(wù)

Java spring單點(diǎn)登錄系統(tǒng)

2.1添加依賴(lài)

      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      <dependency>
          <groupId>com.alibaba.cloud</groupId>
          <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
      </dependency>
      <dependency>
          <groupId>com.alibaba.cloud</groupId>
          <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
      </dependency>
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-oauth2</artifactId>
      </dependency>
      <dependency>
          <groupId>org.projectlombok</groupId>
          <artifactId>lombok</artifactId>
      </dependency>

2.2 項(xiàng)目配置文件

在sca-auth工程中創(chuàng)建bootstrap.yml文件

server:
port: 8071
spring:
application:
  name: sca-auth
cloud:
  nacos:
    discovery:
      server-addr: localhost:8848
    config:
      server-addr: localhost:8848

2.3添加項(xiàng)目啟動(dòng)類(lèi)

package com.jt;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class ResourceAuthApplication {
  public static void main(String[] args) {
      SpringApplication.run(ResourceAuthApplication.class, args);
  }
}

2.4 啟動(dòng)并訪(fǎng)問(wèn)項(xiàng)目

項(xiàng)目啟動(dòng)時(shí),系統(tǒng)會(huì)默認(rèn)生成一個(gè)登陸密碼

Java spring單點(diǎn)登錄系統(tǒng)

打開(kāi)瀏覽器輸入http://localhost:8071呈現(xiàn)登陸頁(yè)面

Java spring單點(diǎn)登錄系統(tǒng)

默認(rèn)用戶(hù)名為user,密碼為系統(tǒng)啟動(dòng)時(shí),在控制臺(tái)呈現(xiàn)的密碼。執(zhí)行登陸測(cè)試,登陸成功進(jìn)入如下界面(因?yàn)闆](méi)有定義登陸頁(yè)面,所以會(huì)出現(xiàn)404)

 

3. 優(yōu)化進(jìn)一步設(shè)計(jì)

3.1 定義安全配置類(lèi) SecurityConfig

修改SecurityConfig配置類(lèi),添加登錄成功或失敗的處理邏輯

package com.jt.auth.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
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.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

@Configuration//配置對(duì)象--系統(tǒng)啟動(dòng)時(shí)底層會(huì)產(chǎn)生代理對(duì)象,來(lái)初始化一些對(duì)象
public class SecurityConfig extends WebSecurityConfigurerAdapter {
//WebSecurityConfigurerAdapter 類(lèi)是個(gè)適配器, 在配置的時(shí)候,需要我們自己寫(xiě)個(gè)配置類(lèi)去繼承他,然后編寫(xiě)自己所特殊需要的配置
  //BCryptPasswordEncoder密碼加密對(duì)象比MD5安全性更高,MD5暴力反射可以破解過(guò)
  @Bean
  public BCryptPasswordEncoder passwordEncoder(){
      return new BCryptPasswordEncoder();
  }

  /**
   * 配置認(rèn)證管理器(負(fù)責(zé)對(duì)客戶(hù)輸入的用戶(hù)信息進(jìn)行認(rèn)證),在其他配置類(lèi)中會(huì)用到這個(gè)對(duì)象
   * @return
   * @throws Exception
   */
  @Bean
  public AuthenticationManager authenticationManagerBean()
          throws Exception {
      return super.authenticationManagerBean();
  }

  /**在這個(gè)方法中定義登錄規(guī)則
   * 1)對(duì)所有請(qǐng)求放行(當(dāng)前工程只做認(rèn)證)
   * 2)登錄成功信息的返回
   * 3)登錄失敗信息的返回
   * */
  @Override
  protected void configure(HttpSecurity http) throws Exception {
      //禁用跨域
      http.csrf().disable();
      //放行所有請(qǐng)求
      http.authorizeRequests().anyRequest().permitAll();
      //登錄成功與失敗的處理
      http.formLogin()
              .successHandler(successHandler()) // .successHandler(AuthenticationSuccessHandler對(duì)象)
              .failureHandler(failureHandler());
  }

  @Bean
  //構(gòu)建successHandler()方法來(lái)創(chuàng)建AuthenticationSuccessHandler對(duì)象
  public AuthenticationSuccessHandler successHandler(){
//        return new AuthenticationSuccessHandler() {
//            @Override
//            public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
//
//            }
//        }
      return (request,response,authentication) ->{
          //1.構(gòu)建map對(duì)象,封裝響應(yīng)數(shù)據(jù)
          Map<String,Object> map=new HashMap<>();
          map.put("state",200);
          map.put("message","login ok"); //登錄成功返回的響應(yīng)信息
          //2.將map對(duì)象寫(xiě)到客戶(hù)端
          writeJsonToClient(response,map);
      };
  }
  @Bean
  //failureHandler();方法來(lái)創(chuàng)建AuthenticationSuccessHandler對(duì)象
  public AuthenticationFailureHandler failureHandler(){
      return (request,response, e)-> {
          //1.構(gòu)建map對(duì)象,封裝響應(yīng)數(shù)據(jù)
          Map<String,Object> map=new HashMap<>();
          map.put("state",500);
          map.put("message","login failure");//登錄失敗返回的響應(yīng)信息
          //2.將map對(duì)象寫(xiě)到客戶(hù)端
          writeJsonToClient(response,map);
      };
  }
  //提取公共代碼,將對(duì)象轉(zhuǎn)為Json傳給客戶(hù)端, 構(gòu)建writeJsonToClient();
  private void writeJsonToClient(HttpServletResponse response,
                                 Object object) throws IOException { // Object 類(lèi)型,不只是Map類(lèi)型,說(shuō)不準(zhǔn)
      //2.將對(duì)象轉(zhuǎn)換為json
      //Gson-->toJson  (需要自己找依賴(lài))
      //fastjson-->JSON (spring-cloud-starter-alibaba-sentinel)
      //jackson-->writeValueAsString (spring-boot-starter-web)
      String jsonStr=new ObjectMapper().writeValueAsString(object);
      //3.將json字符串寫(xiě)到客戶(hù)端
      PrintWriter writer = response.getWriter();
      writer.println(jsonStr);
      writer.flush();
  }
}

3.2定義用戶(hù)信息處理對(duì)象

正常來(lái)說(shuō),用來(lái)與數(shù)據(jù)庫(kù)中的用戶(hù)信息作對(duì)比,認(rèn)證是否正確,可否授權(quán)

Java spring單點(diǎn)登錄系統(tǒng)

package com.jt.auth.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
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.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.List;

/**
* 登錄時(shí)用戶(hù)信息的獲取和封裝會(huì)在此對(duì)象進(jìn)行實(shí)現(xiàn),
* 在頁(yè)面上點(diǎn)擊登錄按鈕時(shí),會(huì)調(diào)用這個(gè)對(duì)象的loadUserByUsername方法,
* 頁(yè)面上輸入的用戶(hù)名會(huì)傳給這個(gè)方法的參數(shù)
*
*/
@Service
public class UserDetailsServiceImpl implements UserDetailsService {//獲取用戶(hù)詳細(xì)信息的接口
  @Autowired
  //BCryptPasswordEncoder密碼加密對(duì)象
  private BCryptPasswordEncoder passwordEncoder;
  //UserDetails用戶(hù)封裝用戶(hù)信息(認(rèn)證和權(quán)限信息)
  @Override
  //重寫(xiě)UserDetailsService 接口中的 loadUserByUsername();方法,定義用來(lái)核對(duì)數(shù)據(jù)庫(kù)數(shù)據(jù)和授于相應(yīng)的權(quán)限
  public UserDetails loadUserByUsername(String username)
          throws UsernameNotFoundException {
      //1.基于用戶(hù)名查詢(xún)用戶(hù)信息(用戶(hù)名,用戶(hù)狀態(tài),密碼,....)
      //Userinfo userinfo=userMapper.selectUserByUsername(username);數(shù)據(jù)庫(kù)用戶(hù)信息查詢(xún)操作簡(jiǎn)寫(xiě)了
      String encodedPassword=passwordEncoder.encode("123456");
      //2.查詢(xún)用戶(hù)權(quán)限信息(后面訪(fǎng)問(wèn)數(shù)據(jù)庫(kù))
      //這里先給幾個(gè)假數(shù)據(jù)
      List<GrantedAuthority> authorities =
              AuthorityUtils.createAuthorityList(//這里的權(quán)限信息先這么寫(xiě),后面講
                      "sys:res:create", "sys:res:retrieve");
      //3.對(duì)用戶(hù)信息進(jìn)行封裝
      return new User(username,encodedPassword,authorities);
  }
}

3.3 網(wǎng)關(guān)中登陸路由配置

在網(wǎng)關(guān)配置文件中添加如下配置

server:
port: 9001
spring:
application:
  name: sca-resource-gateway
cloud:
  sentinel: #限流設(shè)計(jì)
    transport:
      dashboard: localhost:8180
    eager: true
  nacos:
    discovery:
      server-addr: localhost:8848
    config:
      server-addr: localhost:8848
      file-extension: yml
  gateway:
    discovery:
      locator:
        enabled: true
    routes:
      - id: router02
        uri: lb://sca-auth  #lb表示負(fù)載均衡,底層默認(rèn)使用ribbon實(shí)現(xiàn)
        predicates: #定義請(qǐng)求規(guī)則(請(qǐng)求需要按照此規(guī)則設(shè)計(jì))
          - Path=/auth/login/** #請(qǐng)求路徑設(shè)計(jì),單體架構(gòu)
        filters:
          - StripPrefix=1 #轉(zhuǎn)發(fā)之前去掉path中第一層路徑

3.4基于Postman進(jìn)行訪(fǎng)問(wèn)測(cè)試

啟動(dòng)sca-gateway,sca-auth服務(wù),然后基于postman進(jìn)行訪(fǎng)問(wèn)測(cè)試

Java spring單點(diǎn)登錄系統(tǒng)

3.5 定義登陸頁(yè)面

在sca-resource-ui工程的static目錄中定義login-sso.html 登陸頁(yè)面

<!doctype html>
<html lang="en">
<head>
  <!-- Required meta tags -->
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- Bootstrap CSS -->
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="external nofollow"  rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
  <title>login</title>
</head>
<body>
<div class="container"id="app">
  <h3>Please Login</h3>
  <form>
      <div class="mb-3">
          <label for="usernameId" class="form-label">Username</label>
          <input type="text" v-model="username" class="form-control" id="usernameId" aria-describedby="emailHelp">
      </div>
      <div class="mb-3">
          <label for="passwordId" class="form-label">Password</label>
          <input type="password" v-model="password" class="form-control" id="passwordId">
      </div>
      <button type="button" @click="doLogin()" class="btn btn-primary">Submit</button>
  </form>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
  var vm=new Vue({
      el:"#app",//定義監(jiān)控點(diǎn),vue底層會(huì)基于此監(jiān)控點(diǎn)在內(nèi)存中構(gòu)建dom樹(shù)
      data:{ //此對(duì)象中定義頁(yè)面上要操作的數(shù)據(jù)
          username:"",
          password:""
      },
      methods: {//此位置定義所有業(yè)務(wù)事件處理函數(shù)
          doLogin() {
              //1.定義url
              let url = "http://localhost:9001/auth/oauth/token"
              //2.定義參數(shù)

              let params = new URLSearchParams()
              params.append('username',this.username);
              params.append('password',this.password);
              params.append("client_id","gateway-client");
              params.append("grant_type","password");
              params.append("client_secret","123456");

              //3.發(fā)送異步請(qǐng)求
              axios.post(url, params).then((response) => {
                  debugger
                  console.log(response.data);
                  let result=response.data;
                  //
                  localStorage.setItem("accessToken",result.access_token);
                  location.href="/fileupload.html" rel="external nofollow" 

              })
          }
      }
  });
</script>
</body>
</html>

3.6 構(gòu)建令牌配置對(duì)象

借助JWT(Json Web Token-是一種json格式)方式將用戶(hù)信息轉(zhuǎn)換為json格式,然后進(jìn)行加密,保存用戶(hù)信息到客戶(hù)端,然后發(fā)送在客戶(hù)端客戶(hù)端接收到這個(gè)JWT之后,保存在客戶(hù)端,之后帶著JWT訪(fǎng)問(wèn)其它模塊時(shí),資源服務(wù)器解析獲得用戶(hù)信息,進(jìn)行訪(fǎng)問(wèn),達(dá)到解放內(nèi)存的目的
config 目錄下 TokenConfig類(lèi)

package com.jt.auth.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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;
/*
*創(chuàng)建jwt類(lèi)型令牌
*構(gòu)建令牌的構(gòu)成有三部分:
* header(頭部信息:令牌類(lèi)型)/
* payload(數(shù)據(jù)信息-用戶(hù)信息,權(quán)限信息)/
* SIGNATURE(簽名信息-對(duì)header和payload部分加密)
* */
@Configuration //配置對(duì)象--系統(tǒng)啟動(dòng)時(shí)底層會(huì)產(chǎn)生代理對(duì)象,來(lái)初始化一些對(duì)象
public class TokenConfig {
  //定義令牌簽發(fā)口令(暗號(hào),規(guī)則),解密口令
  //當(dāng)客戶(hù)端在執(zhí)行登錄時(shí),加入有攜帶這個(gè)信息,認(rèn)證服務(wù)器可以簽發(fā)令牌
  
  private String SIGNING_KEY = "auth"; 在對(duì)header和payload簽名時(shí),需要的一個(gè)口令
  //構(gòu)建令牌生成器對(duì)象()
  @Bean
  public TokenStore tokenStore(){
      return new JwtTokenStore(jwtAccessTokenConverter());//令牌生成器(jwt轉(zhuǎn)換器)
  }
 
  @Bean
   //Jwt轉(zhuǎn)換器,將任何數(shù)據(jù)轉(zhuǎn)換為jwt字符串
  public JwtAccessTokenConverter jwtAccessTokenConverter(){
      JwtAccessTokenConverter converter=new JwtAccessTokenConverter();
      //設(shè)置加密/解密口令
      converter.setSigningKey(SIGNING_KEY);
      return converter;
  }
  
}

Java spring單點(diǎn)登錄系統(tǒng)

創(chuàng)建認(rèn)證管理器對(duì)象

在SecurityConfig中添加如下方法(后面授權(quán)服務(wù)器會(huì)用到):

  /**
   * 配置認(rèn)證管理器(負(fù)責(zé)對(duì)客戶(hù)輸入的用戶(hù)信息進(jìn)行認(rèn)證),在其他配置類(lèi)中會(huì)用到這個(gè)對(duì)象
   * @return
   * @throws Exception
   */
  @Bean
  public AuthenticationManager authenticationManagerBean()
          throws Exception {
      return super.authenticationManagerBean();
  }

3.7 定義認(rèn)證授權(quán)核心配置

授權(quán)服務(wù)器的核心配置

package com.jt.auth.config;

import lombok.AllArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
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.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;

import java.util.Arrays;

/**
* 完成所有配置的組裝,在這個(gè)配置類(lèi)中完成認(rèn)證授權(quán),JWT令牌簽發(fā)等配置操作
* 1)SpringSecurity (安全認(rèn)證和授權(quán))
* 2)TokenConfig
* 3)Oauth2(暫時(shí)不說(shuō))
*/

@AllArgsConstructor
@Configuration
@EnableAuthorizationServer //開(kāi)啟認(rèn)證和授權(quán)服務(wù)
public class Oauth2Config extends AuthorizationServerConfigurerAdapter {
  //此對(duì)象負(fù)責(zé)完成認(rèn)證管理
  private AuthenticationManager authenticationManager;
  //TokenStore負(fù)責(zé)完成令牌創(chuàng)建,信息讀取
  private TokenStore tokenStore;
  //負(fù)責(zé)獲取用戶(hù)詳情信息(username,password,client_id,grant_type,client_secret)
  //private ClientDetailsService clientDetailsService;
  //JWT令牌轉(zhuǎn)換器(基于用戶(hù)信息構(gòu)建令牌,解析令牌)
  private JwtAccessTokenConverter jwtAccessTokenConverter;
  //密碼加密匹配器對(duì)象
  private PasswordEncoder passwordEncoder;
  //負(fù)責(zé)獲取用戶(hù)信息信息
  private UserDetailsService userDetailsService;

  //設(shè)置認(rèn)證端點(diǎn)的配置(/oauth/token),客戶(hù)端通過(guò)這個(gè)路徑獲取JWT令牌
  @Override
  public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
      endpoints
      //配置認(rèn)證管理器
      .authenticationManager(authenticationManager)
      //驗(yàn)證用戶(hù)的方法獲得用戶(hù)詳情
      .userDetailsService(userDetailsService)
      //要求提交認(rèn)證使用post請(qǐng)求方式,提高安全性
      .allowedTokenEndpointRequestMethods(HttpMethod.POST,HttpMethod.GET)
      //要配置令牌的生成,由于令牌生成比較復(fù)雜,下面有方法實(shí)現(xiàn)
      .tokenServices(tokenService());//這個(gè)不配置,默認(rèn)令牌為UUID.randomUUID().toString()
  }

  //定義令牌生成策略
  @Bean
  public AuthorizationServerTokenServices tokenService(){
      //這個(gè)方法的目標(biāo)就是獲得一個(gè)令牌生成器
      DefaultTokenServices services=new DefaultTokenServices();
      //支持令牌刷新策略(令牌有過(guò)期時(shí)間)
      services.setSupportRefreshToken(true);
      //設(shè)置令牌生成策略(tokenStore在TokenConfig配置了,本次我們應(yīng)用JWT-定義了一種令牌格式)
      services.setTokenStore(tokenStore);
      //設(shè)置令牌增強(qiáng)(固定用法-令牌Payload部分允許添加擴(kuò)展數(shù)據(jù),例如用戶(hù)權(quán)限信息)
      TokenEnhancerChain chain=new TokenEnhancerChain();
      chain.setTokenEnhancers(
              Arrays.asList(jwtAccessTokenConverter));
      //令牌增強(qiáng)對(duì)象設(shè)置到令牌生成
      services.setTokenEnhancer(chain);
      //設(shè)置令牌有效期
      services.setAccessTokenValiditySeconds(3600);//1小時(shí)
      //刷新令牌應(yīng)用場(chǎng)景:一般在用戶(hù)登錄系統(tǒng)后,令牌快過(guò)期時(shí),系統(tǒng)自動(dòng)幫助用戶(hù)刷新令牌,提高用戶(hù)的體驗(yàn)感
      services.setRefreshTokenValiditySeconds(3600*72);//3天
      //配置客戶(hù)端詳情
      //services.setClientDetailsService(clientDetailsService);
      return services;
  }

  //設(shè)置客戶(hù)端詳情類(lèi)似于用戶(hù)詳情
  @Override
  public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
      clients.inMemory()
      //客戶(hù)端id
      .withClient("gateway-client")
      //客戶(hù)端秘鑰
      .secret(passwordEncoder.encode("123456"))
      //設(shè)置權(quán)限
      .scopes("all")//all只是個(gè)名字而已和寫(xiě)abc效果相同
      //允許客戶(hù)端進(jìn)行的操作  里面的字符串千萬(wàn)不能寫(xiě)錯(cuò)
      .authorizedGrantTypes("password","refresh_token");
  }
  // 認(rèn)證成功后的安全約束配置
  @Override
  public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
      //認(rèn)證通過(guò)后,允許客戶(hù)端進(jìn)行哪些操作
      security
      //公開(kāi)oauth/token_key端點(diǎn)
      .tokenKeyAccess("permitAll()")
      //公開(kāi)oauth/check_token端點(diǎn)
      .checkTokenAccess("permitAll()")
      //允許提交請(qǐng)求進(jìn)行認(rèn)證(申請(qǐng)令牌)
      .allowFormAuthenticationForClients();
  }
}

Postman訪(fǎng)問(wèn)測(cè)試

第一步:?jiǎn)?dòng)服務(wù)
依次啟動(dòng)sca-auth服務(wù),sca-resource-gateway,sca-resource-ui服務(wù)。

第二步:檢測(cè)sca-auth服務(wù)控制臺(tái)的Endpoints信息,例如:

Java spring單點(diǎn)登錄系統(tǒng)

打開(kāi)postman進(jìn)行登陸訪(fǎng)問(wèn)測(cè)試

Java spring單點(diǎn)登錄系統(tǒng)

{
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MzAwNzYxMTAsInVzZXJfbmFtZSI6ImphY2siLCJhdXRob3JpdGllcyI6WyJzeXM6cmVzOmNyZWF0ZSIsInN5czpyZXM6cmV0cmlldmUiXSwianRpIjoiM2Q0MzExOTYtYmRkZi00Y2NhLWFmMDMtNWMzNGM4ZmJkNzQ3IiwiY2xpZW50X2lkIjoiZ2F0ZXdheS1jbGllbnQiLCJzY29wZSI6WyJhbGwiXX0.GnrlqsZMSdagDaRQDZWDLbY7I7KUlXQgyXATcXXS6FI",
  "token_type": "bearer",
 

 

4 資源服務(wù)器配置Csca-resource

Java spring單點(diǎn)登錄系統(tǒng)

4.1 構(gòu)建令牌配置對(duì)象

package com.jt.resource.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
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;

/*
*創(chuàng)建jwt類(lèi)型令牌
*構(gòu)建令牌的構(gòu)成有三部分:
* header(頭部信息:令牌類(lèi)型)/
* payload(數(shù)據(jù)信息-用戶(hù)信息,權(quán)限信息)/
* SIGNATURE(簽名信息-對(duì)header和payload部分加密)
* */
@Configuration //配置對(duì)象--系統(tǒng)啟動(dòng)時(shí)底層會(huì)產(chǎn)生代理對(duì)象,來(lái)初始化一些對(duì)象
public class TokenConfig {
  //定義令牌簽發(fā)口令(暗號(hào),規(guī)則),解密口令
  //當(dāng)客戶(hù)端在執(zhí)行登錄時(shí),加入有攜帶這個(gè)信息,認(rèn)證服務(wù)器可以簽發(fā)令牌
  //在對(duì)header和payload簽名時(shí)
  private String SIGNING_KEY = "auth";
  //構(gòu)建令牌生成器對(duì)象()
  @Bean
  public TokenStore tokenStore(){
      return new JwtTokenStore(jwtAccessTokenConverter());//令牌生成器(轉(zhuǎn)換器)
  }
  //Jwt轉(zhuǎn)換器,將任何數(shù)據(jù)轉(zhuǎn)換為jwt字符串
  @Bean
  public JwtAccessTokenConverter jwtAccessTokenConverter(){
      JwtAccessTokenConverter converter=new JwtAccessTokenConverter();
      //設(shè)置加密/解密口令
      converter.setSigningKey(SIGNING_KEY);
      return converter;
  }
}

4.2 資源服務(wù)令牌解析配置

2.將對(duì)象轉(zhuǎn)換為json
      //Gson-->toJson  (需要自己找依賴(lài))
      //fastjson-->JSON (spring-cloud-starter-alibaba-sentinel)
      //jackson-->writeValueAsString (spring-boot-starter-web)
package com.jt.resource.config;

import com.alibaba.fastjson.JSON;
import com.google.gson.Gson;
import com.fasterxml.jackson.databind.ObjectMapper;
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.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler;

import javax.servlet.http.HttpServletResponse;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

/**
* 資源服務(wù)器的配置,在這個(gè)對(duì)象
* 1)JWT 令牌解析配置(客戶(hù)端帶著令牌訪(fǎng)問(wèn)資源時(shí),要對(duì)令牌進(jìn)行解析)
* 2) 啟動(dòng)資源訪(fǎng)問(wèn)的授權(quán)配置(不是所有登陸用戶(hù)可以訪(fǎng)問(wèn)所有資源)
*/
@Configuration
@EnableResourceServer 此注解會(huì)啟動(dòng)資源服務(wù)器的默認(rèn)配置
@EnableGlobalMethodSecurity(prePostEnabled = true) //執(zhí)行方法之前啟動(dòng)權(quán)限檢查
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

  @Autowired
  private TokenStore tokenStore;
  /**
   * token服務(wù)配置
   */
  @Override
  public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
      //super.configure(resources);
      //定義令牌生成策略,這里不是要?jiǎng)?chuàng)建令牌,是要解析令牌
      resources.tokenStore(tokenStore);
  }
  /**
   * 路由安全認(rèn)證配置
   */
  @Override
  public void configure(HttpSecurity http) throws Exception {
      //super.configure(http);
      http.csrf().disable();//關(guān)閉跨域攻擊
      //放行所有的資源訪(fǎng)問(wèn)(對(duì)資源的方問(wèn)不做認(rèn)證)
      http.authorizeRequests().anyRequest().permitAll();
      //http.authorizeRequests().mvcMatchers("/resource/**")
      //        .authenticated(); //假如沒(méi)有認(rèn)證就訪(fǎng)問(wèn)會(huì)報(bào)401異常
      //處理異常
      http.exceptionHandling()
              .accessDeniedHandler(accessDeniedHandler()); //403的異常處理  .拒絕訪(fǎng)問(wèn)的處理(AccessDeniedHandler類(lèi)型對(duì)象)
             
  }


  @Bean
  public AccessDeniedHandler accessDeniedHandler() { //返回  AccessDeniedHandler對(duì)象
      return (request,response, exception)->{

          Map<String,Object> map = new HashMap<>();
          map.put("state", HttpServletResponse.SC_FORBIDDEN);//403
          map.put("message", "抱歉,沒(méi)有這個(gè)資源");
          //1設(shè)置響應(yīng)數(shù)據(jù)的編碼
          response.setCharacterEncoding("utf-8");
          //2告訴瀏覽器響應(yīng)數(shù)據(jù)的內(nèi)容類(lèi)型以及編碼
          response.setContentType("application/json;charset=utf-8");
          //2.將對(duì)象轉(zhuǎn)換為json

          //1.fastjson-->JSON (spring-cloud-starter-alibaba-sentinel)
          //String jsonStr= JSON.toJSONString(map);//fastjson
          //2.Gson-->toJson  (需要自己找依賴(lài))
          Gson gson = new Gson();
          String jsonStr = gson.toJson(map);
          //jackson-->writeValueAsString (spring-boot-starter-web)
          //String jsonStr = new ObjectMapper().writeValueAsString(map);
          PrintWriter writer = response.getWriter();
          writer.println(jsonStr);
          writer.flush();
      };
  }
  
}

4.3 設(shè)置資源訪(fǎng)問(wèn)的權(quán)限

在ResourceController的上傳方法上添加 @PreAuthorize(“hasAuthority(‘sys:res:create')”)注解,用于告訴底層框架方法此方法需要具備的權(quán)限,

@PreAuthorize("hasAuthority('sys:res:create')")
@PostMapping("/upload/")
 public String uploadFile(MultipartFile uploadFile) throws IOException {
     ...
 }

不加權(quán)限,會(huì)報(bào)403異常,并且展示我們修改403異常的信息返回在控制臺(tái)上

4.4 啟動(dòng)服務(wù)訪(fǎng)問(wèn)測(cè)試

4.4.1 訪(fǎng)問(wèn)auth認(rèn)證授權(quán)服務(wù)獲取token

啟動(dòng)服務(wù)(sca-auth,sca-resource-gateway,sca-resource)
執(zhí)行POSTMAN ,訪(fǎng)問(wèn) auth認(rèn)證授權(quán)服務(wù) http://localhost:9001/auth/oauth/token, 獲取token

Java spring單點(diǎn)登錄系統(tǒng)

4.4.2 攜帶TOKEN訪(fǎng)問(wèn)資源服務(wù)器

復(fù)制access_token ,請(qǐng)求地址: http://localhost:9001/sca/resource/upload/
1.設(shè)置請(qǐng)求頭(header),要攜帶令牌并指定請(qǐng)求的內(nèi)容類(lèi)型

Java spring單點(diǎn)登錄系統(tǒng)

2. 設(shè)置請(qǐng)求體(body),設(shè)置form-data,key要求為file類(lèi)型,參數(shù)名與你服務(wù)端controller文件上傳方法的參數(shù)名相同,值為你選擇的文件

Java spring單點(diǎn)登錄系統(tǒng)

4.4.3 對(duì)403異常前端頁(yè)面顯示

function upload(file){
      //定義一個(gè)表單
      let form=new FormData();
      //將圖片添加到表單中
      form.append("uploadFile",file);
      let url="http://localhost:9000/sca/resource/upload/";
      //異步提交方式1
      axios.post(url,form,{headers:{"Authorization":"Bearer "+localStorage.getItem("accessToken")}})
           .then(function (response){
               let result=response.data;
               if(result.state==403){
                   alert(result.message);
                   return;
               }
               alert("upload ok");
           })
  }

1.啟動(dòng)服務(wù)(sca-auth,sca-resource-gateway,sca-resource)
2.執(zhí)行登陸 localhost:8080/login-sso.html 獲取access_token令牌
3.攜帶令牌訪(fǎng)問(wèn)資源(url中的前綴"sca"是在資源服務(wù)器中自己指定的,你的網(wǎng)關(guān)怎么配置的,你就怎么寫(xiě))

Java spring單點(diǎn)登錄系統(tǒng)

成功:

Java spring單點(diǎn)登錄系統(tǒng)

403異常,沒(méi)有訪(fǎng)問(wèn)權(quán)限

Java spring單點(diǎn)登錄系統(tǒng)

4.5 Oauth2規(guī)范

oauth2定義了一種認(rèn)證授權(quán)協(xié)議,一種規(guī)范,此規(guī)范中定義了四種類(lèi)型的角色:
1)資源有者(User)
2)認(rèn)證授權(quán)服務(wù)器(jt-auth)
3)資源服務(wù)器(jt-resource)
4)客戶(hù)端應(yīng)用(jt-ui)
同時(shí),在這種協(xié)議中規(guī)定了認(rèn)證授權(quán)時(shí)的幾種模式:
1)密碼模式 (基于用戶(hù)名和密碼進(jìn)行認(rèn)證)
2)授權(quán)碼模式(就是我們說(shuō)的三方認(rèn)證:QQ,微信,微博,。。。。)
3)…

4.6 面試問(wèn)題點(diǎn)

單點(diǎn)登陸系統(tǒng)的設(shè)計(jì)架構(gòu)(微服務(wù)架構(gòu))
服務(wù)的設(shè)計(jì)及劃分(資源服務(wù)器,認(rèn)證服務(wù)器,網(wǎng)關(guān)服務(wù)器,客戶(hù)端服務(wù))
認(rèn)證及資源訪(fǎng)問(wèn)的流程(資源訪(fǎng)問(wèn)時(shí)要先認(rèn)證再訪(fǎng)問(wèn))
認(rèn)證和授權(quán)時(shí)的一些關(guān)鍵技術(shù)(Spring Security,Jwt,Oauth2)
FAQ 分析
為什么要單點(diǎn)登陸(分布式系統(tǒng),再訪(fǎng)問(wèn)不同服務(wù)資源時(shí),不要總是要登陸,進(jìn)而改善用戶(hù)體驗(yàn))
單點(diǎn)登陸解決方案?(市場(chǎng)常用兩種: spring security+jwt+oauth2,spring securit+redis+oauth2)
Spring Security 是什么?(spring框架中的一個(gè)安全默認(rèn),實(shí)現(xiàn)了認(rèn)證和授權(quán)操作)
JWT是什么?(一種令牌格式,一種令牌規(guī)范,通過(guò)對(duì)JSON數(shù)據(jù)采用一定的編碼,加密進(jìn)行令牌設(shè)計(jì))
OAuth2是什么?(一種認(rèn)證和授權(quán)規(guī)范,定義了單點(diǎn)登陸中服務(wù)的劃分方式,認(rèn)證的相關(guān)類(lèi)型)

 

5 Bug 分析

401 : 訪(fǎng)問(wèn)資源時(shí)沒(méi)有認(rèn)證。
403 : 訪(fǎng)問(wèn)資源時(shí)沒(méi)有權(quán)限。
404:訪(fǎng)問(wèn)的資源找不到(一定要檢查你訪(fǎng)問(wèn)資源的url)
405: 請(qǐng)求方式不匹配(客戶(hù)端請(qǐng)求方式是GET,服務(wù)端處理請(qǐng)求是Post就是這個(gè)問(wèn)題)
500: 不看后臺(tái)無(wú)法解決?(error,warn)

到此這篇關(guān)于Java spring單點(diǎn)登錄系統(tǒng)的文章就介紹到這了,更多相關(guān)Java單點(diǎn)登錄內(nèi)容請(qǐng)搜索服務(wù)器之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持服務(wù)器之家!

原文鏈接:https://blog.csdn.net/weixin_58678891/article/details/119959552

延伸 · 閱讀

精彩推薦
  • Java教程xml與Java對(duì)象的轉(zhuǎn)換詳解

    xml與Java對(duì)象的轉(zhuǎn)換詳解

    這篇文章主要介紹了xml與Java對(duì)象的轉(zhuǎn)換詳解的相關(guān)資料,需要的朋友可以參考下...

    Java教程網(wǎng)2942020-09-17
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程Java實(shí)現(xiàn)搶紅包功能

    Java實(shí)現(xiàn)搶紅包功能

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)搶紅包功能,采用多線(xiàn)程模擬多人同時(shí)搶紅包,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關(guān)于小米推送Java代碼,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧...

    富貴穩(wěn)中求8032021-07-12
  • Java教程Java8中Stream使用的一個(gè)注意事項(xiàng)

    Java8中Stream使用的一個(gè)注意事項(xiàng)

    最近在工作中發(fā)現(xiàn)了對(duì)于集合操作轉(zhuǎn)換的神器,java8新特性 stream,但在使用中遇到了一個(gè)非常重要的注意點(diǎn),所以這篇文章主要給大家介紹了關(guān)于Java8中S...

    阿杜7482021-02-04
  • Java教程Java BufferWriter寫(xiě)文件寫(xiě)不進(jìn)去或缺失數(shù)據(jù)的解決

    Java BufferWriter寫(xiě)文件寫(xiě)不進(jìn)去或缺失數(shù)據(jù)的解決

    這篇文章主要介紹了Java BufferWriter寫(xiě)文件寫(xiě)不進(jìn)去或缺失數(shù)據(jù)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望...

    spcoder14552021-10-18
  • Java教程20個(gè)非常實(shí)用的Java程序代碼片段

    20個(gè)非常實(shí)用的Java程序代碼片段

    這篇文章主要為大家分享了20個(gè)非常實(shí)用的Java程序片段,對(duì)java開(kāi)發(fā)項(xiàng)目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
  • Java教程升級(jí)IDEA后Lombok不能使用的解決方法

    升級(jí)IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級(jí),尋思已經(jīng)有好久沒(méi)有升過(guò)級(jí)了。升級(jí)完畢重啟之后,突然發(fā)現(xiàn)好多錯(cuò)誤,本文就來(lái)介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
主站蜘蛛池模板: 亚洲综合视频 | 91精品国产高清久久久久久久久 | 亚洲一级毛片 | 日韩精品一区二区三区中文字幕 | 日本三级电影网站 | 国产精品成人3p一区二区三区 | 久久久看片 | 亚洲午夜免费视频 | 国产婷婷精品 | 国产一区不卡视频 | 国产视频三区 | 国产黄色大全 | 国产精品久久久 | 亚洲 欧美 日韩 在线 | 久久一区二区三区四区 | 日韩欧美第一页 | 日本不卡一二三区 | 黄色影院在线观看 | 激情综合五月网 | 超碰伊人网 | 国产精品18久久久 | 在线观看一区二区三区视频 | 精品久久一区二区三区 | 奇米二区 | 黄色免费毛片 | 亚洲精品一区在线观看 | 欧美人成在线视频 | 一区二区在线不卡 | 在线观看免费视频国产 | 免费一级毛片在线观看 | 视频一区二区三区在线播放 | 亚洲三区电影 | 在线日韩视频 | 国内精品视频在线观看 | 日本免费精品视频 | 国产精品视频网 | 久久久www成人免费无遮挡大片 | 群p在线观看 | 中文字幕日韩av | 久久久久久久久久久久久久免费看 | 在线免费日韩 |