作為一位專業的程式設計師,我將為您提供一份詳細的中文繁體版教學指南,內容涉及如何使用前端框架 UniApp 和後端 Spring Boot 來實現一個具備微信小程序授權登錄功能的全端專案範例。以下是一個完整的指導流程:
前置作業與環境設置
1.1 安裝必要軟體
- Node.js – Node.js 是 JavaScript 的執行環境,用於前端開發。
- Git – Git 是一種版本控制系統,方便團隊協同工作和管理代碼變更。
- JDK (Java Development Kit) – Java Development Kit 是編寫、編譯、運行 Java 應用程式的必要組件。
- Maven – Maven 是用於管理 Java 專案的依賴關係和生命週期的工具。
- Visual Studio Code – Visual Studio Code 是一款跨平臺的開源集成式開發環境 (IDE),適合各種類型的程式設計。
1.2 建立專案結構
首先,我們需要創建兩個獨立的專案,分別代表前端的 UniApp 部分和後端的 Spring Boot 部分。在您的電腦上創建如下目錄結構:
├── backend # 後端 Spring Boot 專案
│ └── pom.xml # Maven POM 檔案
├── frontend # 前端 UniApp 專案
│ └── App.vue # Vue 單頁面應用入口
│ └── main.js # 主要啟動腳本
└── README.md # 說明文件
1.3 初始化前端專案
進入 `frontend` 資料夾,使用下列命令初始化一個新的 Unipad 專案:
npx uni-cli create my-project
這會生成一個基本的 UniPad 專案骨架,包含必要的配置檔案和模版。接下來,我們需要在 `main.js` 中進行一些調整以支持微信小程序的登錄邏輯。
1.4 初始化後端專案
進入 `backend` 資料夾,使用 Maven 來初始化一個新的 Spring Boot 專案:
mvn archetype:generate \
-DgroupId=com.example \
-DartifactId=my-spring-boot-app \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DarchetypeVersion=1.4 \
-DinteractiveMode=false
這將創建一個基礎的 Spring Boot 專案,其中包含了 `pom.xml` 和 `src/main/java/com/example/my_spring_boot_app/MySpringBootApp.java` 等基本檔案。接著,我們需要添加支援 OAuth 2.0 的庫到我們的專案中。
整合第三方服務
2.1 申請微信公眾平臺帳號
要讓微信小程序能夠與您的應用程式交互,您必須先申請一個微信公眾平臺帳戶並獲得相關的 API 憑證。請訪問 [微信開放平臺](https://open.weixin.qq.com/) 進行註冊和設定。
2.2 獲取 API Key 和 Secret Key
完成上述步驟後,您應該已經擁有了一個 AppID(API Key)和一個 AppSecret(Secret Key)。這些資訊將用於配置前端和後端應用程式,以便與微信進行通信。
前端授權處理
在前端 UniApp 部分,我們需要實現以下功能:
1. 用戶點擊「登陸」按鈕時,開始授權流程。
2. 在得到用戶同意之後,UniApp 將向後端發送一個具有特定參數的 HTTP POST 請求。
3. 後端驗證這些參數並返回一個有效的 JSON Web Token (JWT)給前端。
4. 前端收到 JWT 後,存儲在本地瀏覽器或設備內部,以便未來使用。
以下是前端部分的實踐步驟:
3.1 更新 `App.vue` 檔案
在 `App.vue` 檔案中,添加一個按鈕來引導用戶進行授權:
<template>
<!-- 其他UI元素省略 -->
<button @click="handleLoginClick">登入</button>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
methods: {
async handleLoginClick() {
// 這裡將放置您的授權邏輯
},
},
});
</script>
3.2 定義授權函數
在 `methods` 對象中定義一個方法來觸發授權流程:
methods: {
async handleLoginClick() {
const authResponse = await this.$u.weixin.login(); // 這是 UniApp 提供的原生微信登入方法
if (authResponse.code) {
console.log('成功取得授權碼:', authResponse.code);
this.requestAccessToken(authResponse.code); // 這個方法稍後定義
} else {
console.error('授權失敗');
}
},
},
注意:上述代碼假設 `$u.weixin.login()` 可以正常運行並且從微信那裡獲得一個授權碼 `code`。實際情況下,您可能需要根據微信的 SDK 手冊來確保此過程的正確性。
3.3 請求 Access Token
當有了授權碼 (`code`) 後,我們需要用它來換回一個 Access Token:
methods: {
async requestAccessToken(code) {
try {
const response = await fetch('/api/token', {
method: 'POST',
headers: new Headers({ 'Content-Type': 'application/json' }),
body: JSON.stringify({ code }),
});
const data = await response.json();
if (response.ok && data.access_token) {
localStorage.setItem('access_token', data.access_token); // 將 token 存儲在本地的瀏覽器儲存空間
console.log('成功取得 access token:', data.access_token);
} else {
console.error('錯誤取得 access token:', data.message || '未知錯誤');
}
} catch (err) {
console.error('發生錯誤:', err);
}
},
},
這個方法是異步的,因為它是通過網路向後端請求資源。它使用了 Fetch API 來發起一個 POST 請求,要求後端返回一個 Access Token。一旦拿到 Access Token,就把它存儲在本地瀏覽器的儲存空間中。
3.4 更新 `main.js`
為了使前端能夠與後端通訊,我們還需要修改 `main.js` 中的配置:
import router from '@/router';
router.beforeEach((to, from, next) => {
if (to.meta.requiresAuth && !localStorage.getItem('access_token')) {
next({ name: 'SignIn' }); // 如果沒有有效的 Access Token,重定向至簽名頁面
} else {
next(); // 否則允許路徑轉移
}
});
這個路由守護程序檢查每個即將被渲染的路由是否標記了 `requiresAuth` 元數據屬性。如果標記了且缺少有效 Access Token,那麼用戶將會被重定向到一個簽名的頁面。這樣做可以保護某些路由僅限已授權用戶訪問。
後端認證邏輯
在後端 Spring Boot 部分,我們需要實現以下功能:
1. 接收來自前端 Unipad 的 HTTP POST 請求。
2. 判斷請求的有效性和合法性。
3. 根據收到的授權碼 `code`,從微信 API 獲取用戶信息。
4. 驗證用戶信息並創建或更新用戶資料。
5. 生成一個 JWT 令牌並返回給前端。
4.1 新增依賴
首先,我們需要為專案添加幾個重要的依賴項:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</groupId>
<!-- 新增以下依賴 -->
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</groupId>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</groupId>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
</groupId>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>1.9.2</version>
</groupId>
</dependencies>
這些依賴將用於網頁視圖、HTTP 客戶端操作、JWT 生成和解碼以及 Swagger UI 的展示。
4.2 新建控制器
在 `src/main/java/com/example/my_spring_boot_app` 資料夾中,新增一個 `Controller` 類別:
@RestController
public class AuthController {
private final static String WEIXIN_AUTH_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code";
@PostMapping("/token")
public ResponseEntity<Object> generateToken(@RequestBody Map<String, Object> params) throws UnsupportedEncodingException {
String appId = (String)params.get("appId"); // 從前端傳來的值
String secretKey = "YOUR_SECRET_KEY"; // 填入您的密匙
String code = (String)params.get("code"); // 從前端傳來的值
String url = String.format(WEIXIN_AUTH_URL, appId, URLEncoder.encode(secretKey, StandardCharsets.UTF_8.toString()), code);
HttpClient client = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url);
CloseableHttpResponse response = client.execute(httpGet);
Map<String, String> result = new HashMap<>();
BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
String line;
while ((line = br.readLine()) != null) {
result.put(line, "");
}
br.close();
String accessToken = result.get("access_token");
String openId = result.get("openid");
String refreshToken = result.get("refresh_token");
Date nowTime = new Date();
long timeMillis = nowTime.getTime();
SimpleGrantedAuthority role = new SimpleGrantedAuthority("ROLE_USER");
UserPrincipal userInfo = new UserPrincipal(openId, accessToken, refreshToken, role, timeMillis + 60 * 60 * 1000); // 存儲使用者資訊
String jwtToken = Jwts.builder()
.setSubject(openId)
.claim("role", role.getAuthority())
.signWith(SignatureAlgorithm.HS512, "YOUR_SIGNING_KEY") // 填入您的簽名金鑰
.compact();
return new ResponseEntity<>(userInfo, HttpStatus.OK);
}
}
這個控制器接受一個帶有 `appId` 和 `code` 參數的 POST 請求。它使用這些參數來呼叫微信的 API 以獲取用戶的 OpenID、Access Token 和 Refresh Token。然後,這些資訊被用來創建一個 `UserPrincipal` 物件,該物件包含了用戶的基本信息和其角色。最後,使用 `JJWT` 庫生成了一個有效的 JWT 令牌。
4.3 安全性設定
為了保護 RESTful API,我們可以在 `SecurityConfig.java` 中新增一些安全配置:
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable().cors().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and().authorizeRequests()
.antMatchers("/", "/index", "/favicon.ico", "/css/**", "/js/**", "/images/**", "/swagger-ui.html", "/v2/api-docs", "/webjars/**").permitAll()
.anyRequest().authenticated().and().addFilterBefore(new JWTAuthenticationFilter(authenticationManagerBean(), cookieUtil), UsernamePasswordAuthenticationFilter.class);
}
}
在上述配置中,我們禁用了 CSRF 保護,啟用了跨域資源共享(CORS),並配置了基於 JWT 的身份驗證過濾器。只有經過授權的路由才能被未經授權的用戶訪問,而所有其他的請求都需要有效的 JWT 令牌。
4.4 新增 Swagger UI
為了簡化 API 的測試和文檔化,我們可以使用 Swagger UI。首先,我們需要在 `pom.xml` 中添加相應的依賴:
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>swagger-bootstrap-ui</artifactId>
<version>1.9.2</version>
</groupId>
然後,在 `Application.java` 中增加註解 `@MapperScan(“com.example.mappers”)` 以映射 MyBatis XML 映射配置。
最後,啟動應用程式,打開 `http://localhost:[your-port]/doc.html`,就可以看到 Swagger UI 介面的全貌了。
結論
透過以上步驟,我們成功地構建了一個結合了前端 Unipad 和後端 Spring Boot 的全端應用程式,並且實現了微信小程序的授權登錄功能。這一過程中涉及到許多不同的技術和概念,如前端開發、後端服務、OAuth 2.0 協議、JSON Web Tokens 等等。希望本文能夠幫助您更好地理解和掌握這些知識點,並靈活運用到自己的項目中去。