欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于SpringBoot + Android實現(xiàn)登錄功能

 更新時間:2024年11月26日 08:52:14   作者:繁依Fanyi  
在移動互聯(lián)網(wǎng)的今天,許多應(yīng)用需要通過移動端實現(xiàn)與服務(wù)器的交互功能,其中登錄是最常見且基礎(chǔ)的一種功能,本篇博客將詳細介紹如何使用 Spring Boot 和 Android 實現(xiàn)一個完整的登錄功能,需要的朋友可以參考下

引言

在移動互聯(lián)網(wǎng)的今天,許多應(yīng)用需要通過移動端實現(xiàn)與服務(wù)器的交互功能,其中登錄是最常見且基礎(chǔ)的一種功能。通過登錄,用戶可以獲得獨特的身份標識,從而訪問特定的資源或服務(wù)。本篇博客將詳細介紹如何使用 Spring Boot 和 Android 實現(xiàn)一個完整的登錄功能,從后端 API 的構(gòu)建到 Android 端的交互,旨在為讀者提供一套完整的解決方案。

1. 簡單分析

在討論如何實現(xiàn)登錄功能之前,我們需要明確需求。通常情況下,登錄功能會包含以下幾個需求:

  • 用戶登錄:用戶通過輸入用戶名(或手機號、郵箱)和密碼進行登錄。
  • 身份驗證:服務(wù)器需要驗證用戶身份是否合法,是否擁有訪問權(quán)限。
  • Token 授權(quán):為了避免頻繁的登錄操作,服務(wù)器可以返回一個 token,客戶端持有該 token 后,能夠在一段時間內(nèi)免除再次登錄。
  • 安全性:需要防止常見的攻擊手段,如密碼泄露、暴力 破解等。

在本項目中,我們將采用基于 JWT(JSON Web Token) 的方式來實現(xiàn)無狀態(tài)的登錄功能,Spring Boot 作為后端框架,Android 作為前端實現(xiàn)登錄頁面及 Token 管理。

2. 項目環(huán)境配置

2.1 后端:Spring Boot 配置

首先,我們需要在后端使用 Spring Boot 作為服務(wù)端框架,選擇 Spring Security 進行用戶身份驗證,并使用 JWT 實現(xiàn)無狀態(tài)的登錄管理。

  1. 創(chuàng)建 Spring Boot 項目
    可以通過 Spring Initializr 快速生成項目骨架,選擇如下依賴:

    • Spring Web
    • Spring Security
    • Spring Data JPA
    • MySQL(或其他數(shù)據(jù)庫)
    • JWT(通過 Maven 手動引入依賴)
  2. JWT 依賴引入
    在 pom.xml 文件中添加 JWT 的依賴:

<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.11.2</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.11.2</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId>
    <version>0.11.2</version>
</dependency>

2.2 前端:Android 項目配置

在 Android 中,我們可以使用 Retrofit 作為網(wǎng)絡(luò)請求庫,并通過 SharedPreferences 來存儲 token 信息。

  • Retrofit 依賴引入
    在 Android 項目的 build.gradle 文件中添加 Retrofit 及其相關(guān)依賴:
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
  • 設(shè)計用戶登錄界面登錄界面是用戶進行身份驗證的入口,通常包含用戶名(或手機號)、密碼輸入框,以及登錄按鈕。

3. Spring Boot 后端開發(fā)

在這一部分,我們將重點介紹后端的開發(fā),首先從用戶模型的設(shè)計開始,然后是 Spring Security 的配置,接著是 JWT 的集成與登錄 API 的實現(xiàn)。

3.1 用戶模型設(shè)計

為了保存用戶信息,我們首先需要設(shè)計一個用戶模型。在這里,我們使用 JPA(Java Persistence API)來定義用戶實體,并將其持久化到數(shù)據(jù)庫中。

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String username;
    private String password;
    private String email;
    
    // other fields, getters and setters
}

同時,使用 UserRepository 進行數(shù)據(jù)操作:

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    Optional<User> findByUsername(String username);
}

3.2 Spring Security 配置

Spring Security 是 Spring 框架提供的強大的安全管理模塊。在這里,我們需要對 Spring Security 進行配置,使其與 JWT 配合使用,來實現(xiàn)無狀態(tài)的身份驗證。

3.2.1 安全配置類

創(chuàng)建一個 SecurityConfig 類,用于配置 Spring Security:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Autowired
    private JwtAuthenticationFilter jwtAuthenticationFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeRequests()
            .antMatchers("/login").permitAll()
            .anyRequest().authenticated()
            .and()
            .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService())
            .passwordEncoder(passwordEncoder());
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

這里我們禁用了 CSRF 保護,因為我們將使用 JWT 進行身份驗證。我們也配置了 jwtAuthenticationFilter,它將在每次請求時驗證 JWT。

3.3 JWT 的集成

JWT 是一種用于在網(wǎng)絡(luò)應(yīng)用之間安全傳輸信息的緊湊令牌。每個 JWT 都由三部分組成:Header、Payload 和 Signature。下面,我們來實現(xiàn)生成和解析 JWT 的邏輯。

3.3.1 JwtTokenUtil 工具類

創(chuàng)建一個 JwtTokenUtil 工具類,用于生成和驗證 JWT。

@Component
public class JwtTokenUtil {

    private static final String SECRET_KEY = "your_secret_key";

    public String generateToken(UserDetails userDetails) {
        return Jwts.builder()
                .setSubject(userDetails.getUsername())
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10))
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
                .compact();
    }

    public String extractUsername(String token) {
        return Jwts.parser()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(token)
                .getBody()
                .getSubject();
    }

    public boolean validateToken(String token, UserDetails userDetails) {
        final String username = extractUsername(token);
        return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
    }

    private boolean isTokenExpired(String token) {
        final Date expiration = Jwts.parser()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(token)
                .getBody()
                .getExpiration();
        return expiration.before(new Date());
    }
}

3.3.2 JwtAuthenticationFilter

JwtAuthenticationFilter 用于攔截請求并驗證 token,確保只有經(jīng)過身份驗證的用戶可以訪問受保護的資源。

@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private UserDetailsService userDetailsService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
            throws ServletException, IOException {

        final String authorizationHeader = request.getHeader("Authorization");

        String username = null;
        String jwt = null;

        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
            jwt = authorizationHeader.substring(7);
            username = jwtTokenUtil.extractUsername(jwt);
        }

        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {

            UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);

            if (jwtTokenUtil.validateToken(jwt, userDetails)) {

                UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities());
                authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            }
        }
        filterChain.doFilter(request, response);
    }
}

3.4 登錄 API 實現(xiàn)

在服務(wù)器端,我們需要提供一個登錄的 API,用戶通過該 API 發(fā)送用戶名和密碼,服務(wù)器驗證后生成 JWT 返回給客戶端。

@RestController
public class AuthController {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private UserDetailsService userDetailsService;

    @PostMapping("/login")
    public ResponseEntity<?> createAuthenticationToken

(@RequestBody AuthRequest authRequest) throws Exception {

        try {
            authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(authRequest.getUsername(), authRequest.getPassword())
            );
        } catch (BadCredentialsException e) {
            throw new Exception("Incorrect username or password", e);
        }

        final UserDetails userDetails = userDetailsService
                .loadUserByUsername(authRequest.getUsername());

        final String jwt = jwtTokenUtil.generateToken(userDetails);

        return ResponseEntity.ok(new AuthResponse(jwt));
    }
}

這里,AuthRequest 是用戶登錄時發(fā)送的請求對象,包含用戶名和密碼。而 AuthResponse 是服務(wù)器返回的響應(yīng)對象,包含生成的 JWT。

4. Android 前端開發(fā)

接下來,我們將在 Android 中實現(xiàn)登錄頁面,并與 Spring Boot 后端進行交互。

4.1 使用 Retrofit 進行網(wǎng)絡(luò)請求

Retrofit 是 Android 平臺上廣泛使用的網(wǎng)絡(luò)請求庫。首先,我們定義一個接口用于請求登錄 API。

public interface ApiService {

    @POST("login")
    Call<AuthResponse> login(@Body AuthRequest authRequest);
}

AuthRequest 類對應(yīng)后端的登錄請求體,AuthResponse 類則用來接收服務(wù)器返回的 JWT。

public class AuthRequest {
    private String username;
    private String password;

    // Constructor, getters and setters
}

public class AuthResponse {
    private String jwt;

    // Constructor, getters and setters
}

4.2 登錄頁面設(shè)計與實現(xiàn)

接下來,我們設(shè)計一個簡單的登錄界面,包括兩個 EditText 組件用于輸入用戶名和密碼,外加一個 Button 進行登錄操作。

<EditText
    android:id="@+id/etUsername"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="Username" />

<EditText
    android:id="@+id/etPassword"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="Password"
    android:inputType="textPassword" />

<Button
    android:id="@+id/btnLogin"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Login" />

在 MainActivity.java 中實現(xiàn)登錄邏輯:

public class MainActivity extends AppCompatActivity {

    private EditText etUsername;
    private EditText etPassword;
    private Button btnLogin;

    private ApiService apiService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        etUsername = findViewById(R.id.etUsername);
        etPassword = findViewById(R.id.etPassword);
        btnLogin = findViewById(R.id.btnLogin);

        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl("http://your-server-url/")
                .addConverterFactory(GsonConverterFactory.create())
                .build();

        apiService = retrofit.create(ApiService.class);

        btnLogin.setOnClickListener(v -> login());
    }

    private void login() {
        String username = etUsername.getText().toString();
        String password = etPassword.getText().toString();

        AuthRequest authRequest = new AuthRequest(username, password);
        Call<AuthResponse> call = apiService.login(authRequest);

        call.enqueue(new Callback<AuthResponse>() {
            @Override
            public void onResponse(Call<AuthResponse> call, Response<AuthResponse> response) {
                if (response.isSuccessful()) {
                    String jwt = response.body().getJwt();
                    // Store JWT in SharedPreferences
                    SharedPreferences preferences = getSharedPreferences("my_prefs", MODE_PRIVATE);
                    preferences.edit().putString("jwt", jwt).apply();

                    // Navigate to another activity
                } else {
                    // Handle failure
                }
            }

            @Override
            public void onFailure(Call<AuthResponse> call, Throwable t) {
                // Handle network failure
            }
        });
    }
}

4.3 Token 的存儲和管理

為了在后續(xù)的請求中使用 JWT,我們可以將其存儲在 Android 的 SharedPreferences 中。這樣,用戶登錄后,應(yīng)用在關(guān)閉再打開時依然可以保持登錄狀態(tài)。

            (Call<AuthResponse> call, Response<AuthResponse> response) {
                if (response.isSuccessful()) {
                    AuthResponse authResponse = response.body();
                    String token = authResponse.getJwt();
                    
                    // Store the token using SharedPreferences
                    SharedPreferences sharedPreferences = getSharedPreferences("MyApp", MODE_PRIVATE);
                    SharedPreferences.Editor editor = sharedPreferences.edit();
                    editor.putString("JWT_TOKEN", token);
                    editor.apply();
                    
                    Toast.makeText(MainActivity.this, "Login successful", Toast.LENGTH_SHORT).show();
                    
                    // Navigate to another activity after successful login
                    Intent intent = new Intent(MainActivity.this, DashboardActivity.class);
                    startActivity(intent);
                    finish();
                } else {
                    Toast.makeText(MainActivity.this, "Login failed", Toast.LENGTH_SHORT).show();
                }
            }

            @Override
            public void onFailure(Call<AuthResponse> call, Throwable t) {
                Toast.makeText(MainActivity.this, "Network error", Toast.LENGTH_SHORT).show();
            }
        });
    }
}

在上面的代碼中,login() 方法負責(zé)發(fā)送登錄請求并處理服務(wù)器的響應(yīng)。如果登錄成功,我們將獲取到服務(wù)器返回的 JWT 并將其存儲在 SharedPreferences 中,以便在后續(xù)的請求中使用該 Token 進行身份驗證。

4.3 Token 的存儲和管理

為了保證用戶登錄后的身份驗證,客戶端需要將服務(wù)器返回的 JWT 存儲起來。SharedPreferences 是 Android 中一種輕量級的數(shù)據(jù)存儲方式,非常適合保存類似于 Token 這樣的配置信息。

SharedPreferences sharedPreferences = getSharedPreferences("MyApp", MODE_PRIVATE);
String token = sharedPreferences.getString("JWT_TOKEN", null);

在需要身份驗證的請求中,我們可以從 SharedPreferences 中讀取保存的 Token,并在請求頭中添加該 Token。

OkHttpClient client = new OkHttpClient.Builder()
    .addInterceptor(chain -> {
        Request originalRequest = chain.request();
        String token = sharedPreferences.getString("JWT_TOKEN", null);
        if (token != null) {
            Request newRequest = originalRequest.newBuilder()
                    .header("Authorization", "Bearer " + token)
                    .build();
            return chain.proceed(newRequest);
        }
        return chain.proceed(originalRequest);
    })
    .build();

通過上述代碼,所有發(fā)送的請求將攜帶 JWT,服務(wù)端能夠通過驗證 Token 來判斷用戶是否具有訪問權(quán)限。

5. 完整登錄流程分析

  1. 用戶在 Android 客戶端輸入用戶名和密碼,點擊登錄按鈕。
  2. 客戶端發(fā)送 POST 請求到服務(wù)器的 /login 接口,請求體中包含用戶名和密碼。
  3. 服務(wù)器驗證用戶的身份,如果驗證成功,則生成 JWT 并返回給客戶端。
  4. 客戶端接收到 JWT 后,將其存儲在 SharedPreferences 中。
  5. 后續(xù)請求時,客戶端將 JWT 附加在請求頭中,服務(wù)器根據(jù) JWT 來判斷用戶是否有權(quán)限訪問資源。

6. 安全性及優(yōu)化策略

6.1 HTTPS 加密傳輸

為了確保數(shù)據(jù)傳輸?shù)陌踩?,建議在實際項目中使用 HTTPS 進行加密傳輸,避免用戶的敏感信息(如密碼)被竊取。

6.2 密碼加密存儲

在服務(wù)器端,用戶的密碼不應(yīng)該以明文形式存儲。通常,我們會使用 BCrypt 等加密算法對用戶密碼進行加密后再存儲到數(shù)據(jù)庫中。

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

6.3 Token 的過期管理

JWT 通常會設(shè)置一個過期時間,以確保 Token 不會被長期濫用??蛻舳嗽跈z測到 Token 過期時,應(yīng)提示用戶重新登錄。

6.4 防止暴力 破解

為了防止惡意用戶通過暴力 破解獲取用戶密碼,建議在登錄接口上增加防護機制,如使用驗證碼,或在多次登錄失敗后暫時鎖定用戶賬號。

7. 總結(jié)

本篇博客介紹了如何使用 Spring Boot 和 Android 實現(xiàn)一個完整的登錄功能。從用戶模型的設(shè)計、Spring Security 的配置、JWT 的集成,到 Android 客戶端的登錄頁面實現(xiàn)、網(wǎng)絡(luò)請求和 Token 管理,涵蓋了從后端到前端的所有關(guān)鍵步驟。登錄功能雖然看似簡單,但其背后涉及的安全性和可擴展性都是我們需要重點關(guān)注的。

以上就是基于SpringBoot + Android實現(xiàn)登錄功能的詳細內(nèi)容,更多關(guān)于SpringBoot Android實現(xiàn)登錄的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • mybatis查詢語句揭秘之封裝數(shù)據(jù)

    mybatis查詢語句揭秘之封裝數(shù)據(jù)

    這篇文章主要給大家介紹了關(guān)于mybatis查詢語句揭秘之封裝數(shù)據(jù)的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學(xué)習(xí)或者使用mybatis具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • SpringBoot中AOP的動態(tài)匹配和靜態(tài)匹配詳解

    SpringBoot中AOP的動態(tài)匹配和靜態(tài)匹配詳解

    這篇文章主要介紹了SpringBoot中AOP的動態(tài)匹配和靜態(tài)匹配詳解,在創(chuàng)建代理的時候?qū)δ繕祟惖拿總€連接點使用靜態(tài)切點檢查,如果僅通過靜態(tài)切點檢查就可以知道連接點是不匹配的,則在運行時就不再進行動態(tài)檢查了,需要的朋友可以參考下
    2023-09-09
  • 使用eclipse 實現(xiàn)將springboot項目打成jar包

    使用eclipse 實現(xiàn)將springboot項目打成jar包

    這篇文章主要介紹了使用eclipse 實現(xiàn)將springboot項目打成jar包的流程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • 詳解Java中格式化日期的DateFormat與SimpleDateFormat類

    詳解Java中格式化日期的DateFormat與SimpleDateFormat類

    DateFormat其本身是一個抽象類,SimpleDateFormat 類是DateFormat類的子類,一般情況下來講DateFormat類很少會直接使用,而都使用SimpleDateFormat類完成,下面我們具體來看一下兩個類的用法:
    2016-05-05
  • 一篇文章弄懂Mybatis中#和$的區(qū)別

    一篇文章弄懂Mybatis中#和$的區(qū)別

    mybatis為我們提供了兩種支持動態(tài)sql的語法#{}以及${},兩者都是動態(tài)的向sql語句中傳入需要的參數(shù),下面這篇文章主要給大家介紹了如何通過一篇文章弄懂Mybatis中#和$區(qū)別的相關(guān)資料,需要的朋友可以參考下
    2021-12-12
  • Netty粘包拆包及使用原理詳解

    Netty粘包拆包及使用原理詳解

    Netty是由JBOSS提供的一個java開源框架,現(xiàn)為?Github上的獨立項目。Netty提供異步的、事件驅(qū)動的網(wǎng)絡(luò)應(yīng)用程序框架和工具,用以快速開發(fā)高性能、高可靠性的網(wǎng)絡(luò)服務(wù)器和客戶端程序,這篇文章主要介紹了Netty粘包拆包及使用原理
    2022-08-08
  • SpringBoot整合java診斷工具Arthas解讀

    SpringBoot整合java診斷工具Arthas解讀

    這篇文章主要介紹了SpringBoot整合java診斷工具Arthas,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • 淺析git server“丟失”commit問題

    淺析git server“丟失”commit問題

    這篇文章主要介紹了git server“丟失”commit問題,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-05-05
  • 沒有編輯器的環(huán)境下是如何創(chuàng)建Servlet(Tomcat+Java)項目的?

    沒有編輯器的環(huán)境下是如何創(chuàng)建Servlet(Tomcat+Java)項目的?

    今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識,文章圍繞著在沒有編輯器的環(huán)境下如何創(chuàng)建Servlet(Tomcat+Java)項目展開,文中有非常詳細的介紹及代碼示例,需要的朋友可以參考下
    2021-06-06
  • Springboot apollo原理及使用方法詳解

    Springboot apollo原理及使用方法詳解

    這篇文章主要介紹了Springboot apollo原理及使用方法詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-06-06

最新評論