登录接口实现细节分析与登录接口代码实现

Posted 生产队的大驴and小乌贼来了

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了登录接口实现细节分析与登录接口代码实现相关的知识,希望对你有一定的参考价值。

登录接口实现细节分析

 登陆接口   

  接下我们需要自定义登陆接口,然后让SpringSecurity对这个接口放行,让用户访问这个接口的时候不用登录也能访问。

  ​在接口中我们通过AuthenticationManager的authenticate方法来进行用户认证,所以需要在SecurityConfig中配置把AuthenticationManager注入容器。

​  认证成功的话要生成一个jwt,放入响应中返回。并且为了让用户下回请求时能通过jwt识别出具体的是哪个用户,我们需要把用户信息存入redis,可以把用户id作为key。

登录接口代码实现

    

package com.example.qinghuatokendemo.Controller;

import com.example.qinghuatokendemo.Domain.ResponseResult;
import com.example.qinghuatokendemo.Domain.User;
import com.example.qinghuatokendemo.Service.LoginServcie;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
public class LoginController 


    @Autowired
    private LoginServcie loginServcie;

    @PostMapping("/user/login")
    public ResponseResult login(@RequestBody User user)
        //登录
        return loginServcie.login(user);
    

  

 

package com.example.qinghuatokendemo.Config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter 

      //创建BCryptPasswordEncoder注入容器
    @Bean
    public PasswordEncoder passwordEncoder()
        return new BCryptPasswordEncoder();
    

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception 
        return super.authenticationManagerBean();
    

    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http
                //关闭csrf
                .csrf().disable()
                //不通过Session获取SecurityContext
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .authorizeRequests()
                // 对于登录接口 允许匿名访问
                .antMatchers("/user/login").anonymous()
                // 除上面外的所有请求全部需要鉴权认证
                .anyRequest().authenticated();
    

 

package com.example.qinghuatokendemo.Service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.qinghuatokendemo.Domain.LoginUser;
import com.example.qinghuatokendemo.Domain.User;
import com.example.qinghuatokendemo.Mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.Objects;

@Service
public class UserDetailsServiceImpl implements UserDetailsService 
    @Autowired
    private UserMapper userMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException 
        //查询用户信息
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUserName,username);
        User user = userMapper.selectOne(queryWrapper);
        //如果没有查询到用户就抛出异常
        if (Objects.isNull(user))
            throw new RuntimeException("用户名或者密码错误");
        
        //查询对应的权限信息


        //把数据封装成UserDetails返回
        return new LoginUser(user);
    

 

 

 

打开redis以后

 

测试接口

  

 

 

 

 

Android——MVCMVPMVVM框架实现登录示例

MVC

描述

自如其意,MVC分为三部分:M层、V层、C层。
M层:model层,主要用于逻辑处理。
V层:view层,主要指Activity、Dialog、Fragment,用于视图展示。
C层:controller层,用于视图层与数据层交互,此处由Activity充当。

缺点

视图层与数据层没有完成解耦,随着逻辑增多,会使Activity非常拥堵。

优点

比一个文件闯天下,稍微好一点

MVP

效果图

描述

自如其意,MVP分为三部分:M层、V层、P层。
M层:model层,主要用于逻辑处理。
V层:view层,主要指Activity、Dialog、Fragment,用于视图展示。
P层:presenter层,用于视图层与数据层交互。通过接口实现交互。

缺点

随着逻辑增多,用于实现视图层与数据层交互的接口数据就会增多

优点

数据层与视图层完成解耦

代码解析

视图效果图

建立实体类

public class User{
    private String UserName;
    private String PassWord;
    public User(String UserName,String PassWord){
        this.PassWord = PassWord;
        this.UserName = UserName;
    }
    public User(){

    }

    public String getUserName() {
        return UserName;
    }

    public void setUserName(String userName) {
        UserName = userName;
    }

    public String getPassWord() {
        return PassWord;
    }

    public void setPassWord(String passWord) {
        PassWord = passWord;
    }
}

建立实体类接口

public interface IUser {
    boolean LoginAccount(String userName,String passWord);
}

实现实体类接口

public class exeLogin implements IUser {
    private User user;
    @Override
    public boolean LoginAccount(String userName,String passWord) {
        if (userName.equals( "admin" ) && passWord.equals( "123456" )){
            user = new User(  );
            user.setUserName( userName );
            user.setPassWord( passWord );
            return true;
        }
        return false;
    }
}

设置P层

public class LoginPresenter {
    private exeLogin exeLogin;
    private IMain iMain;
    public LoginPresenter(IMain iMain){
        this.iMain = iMain;
        exeLogin = new exeLogin();
    }
    public void Login(){
        String userName = iMain.getUserName();
        String passWord = iMain.getPassWord();
        boolean isSuccess = exeLogin.LoginAccount( userName,passWord  );
        iMain.Login( isSuccess );
    }

}

建立交互接口

public interface IMain {
    String getUserName();
    String getPassWord();
    void Login(Boolean isLoginSuccess);
}

数据绑定

public class MainActivity extends AppCompatActivity implements IMain{
    private EditText userName,passWord;
    private Button btnLogin;
    private Context context = null;
    private LoginPresenter loginPresenter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate( savedInstanceState );
        setContentView( R.layout.activity_main );
        InitView();
        Listener();
    }
    private void InitView(){
        userName = findViewById( R.id.username );
        passWord = findViewById( R.id.password );
        btnLogin = findViewById( R.id.login );
        loginPresenter = new LoginPresenter( this );
        if (context == null){
            context = MainActivity.this;
        }
    }
    private void Listener(){
        btnLogin.setOnClickListener( new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                loginPresenter.Login();
                Log.d( "TAG","click success" );
            }
        } );
    }

    @Override
    public String getUserName() {
        return userName.getText().toString().trim();
    }

    @Override
    public String getPassWord() {
        return passWord.getText().toString().trim();
    }

    @Override
    public void Login(Boolean isLoginSuccess) {
        if (isLoginSuccess){
            Toast.makeText( MainActivity.this,"Success",Toast.LENGTH_SHORT ).show();
            Log.d( "TAG","Success" );
        }else {
            Toast.makeText( MainActivity.this,"Fail",Toast.LENGTH_SHORT ).show();
            Log.d( "TAG","Fail" );
        }

    }
}

MVVM

效果图

描述

Model层:
数据处理
View层
实体
ViewModel:
实现视图与数据的交互,将二者分离,实现解耦

代码解析

导入dataBinding

dataBinding {
            enabled = true
        }

实体类

public class User extends BaseObservable {
    public String mUserName;
    public String mPassWord;
    public User(){

    }
    public User(String mUserName,String mPassWord){
        this.mUserName = mUserName;
        this.mPassWord = mPassWord;
    }
    @Bindable
    public String getmUserName() {
        return mUserName;
    }
    /**
     * @param mUserName */
    public void setmUserName(String mUserName) {
        this.mUserName = mUserName;
        notifyPropertyChanged( BR.mUserName );

    }
    @Bindable
    public String getmPassWord() {
        return mPassWord;
    }
    /**
     * @param mPassWord */
    public void setmPassWord(String mPassWord) {
        this.mPassWord = mPassWord;
        notifyPropertyChanged( BR.mPassWord );

    }
}

添加 @Bindable,作为xml绑定字段

    @Bindable
    public String getmUserName() {
        return mUserName;
    }

BR是一个自动生成的类,大致内容为将每一个字段添加ID,通过notifyPropertyChanged实现数据更新

    /**
     * @param mUserName */
    public void setmUserName(String mUserName) {
        this.mUserName = mUserName;
        notifyPropertyChanged( BR.mUserName );

    }

建立viewmodel

public class ViewModel {
    private ActivityMainBinding binding;
    public User user;
    public ViewModel(ActivityMainBinding binding,User user){
        this.binding = binding;
        this.user = user;
    }
    public void Login(View view){
        if (user.getmUserName().equals( "admin" ) && user.getmPassWord().equals( "123456" )){
            Log.d( "TAG","success" );
        }else {
            Log.d( "TAG","fail" );
        }
        Log.d( "TAG",user.getmUserName()+"" );
        Log.d( "TAG",user.getmPassWord()+"" );
    }
}

xml绑定数据

注意视图绑定数据层字段时,一个等于=符号产生不同结果,如果没有等于,我在输入框输入的数据,实体类数据不会刷新,加上等号,完成数据双向绑定。

密码输入框中输入123456

   android:text="@={viewmodel.user.mPassWord}"


密码输入框中输入123456,而打印出来是12345,并没有完成双向绑定

   android:text="@{viewmodel.user.mPassWord}"

<?xml version="1.0" encoding="utf-8"?>
<layout
    xmlns:android="http://schemas.android.com/apk/res/android">
    <data>
        <variable
        name="user"
        type="com.franzliszt.mvvmtest.model.User" />
        <variable
            name="viewmodel"
            type="com.franzliszt.mvvmtest.viewmodel.ViewModel" />
    </data>
    <LinearLayout
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        >

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingTop="40dp">
        </LinearLayout>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:paddingLeft="30dp"
            android:text="账号密码登录"
            android:textColor="#000000"
            android:textSize="30sp"
            android:layout_marginTop="20dp"/>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_margin="20dp">
            <EditText
                android:id="@+id/username"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:hint="用户名"
                android:paddingLeft="10dp"
                android:singleLine="true"
                android:textColor="#ff000000"
                android:textSize="15sp"
                android:text="@={viewmodel.user.mUserName}"
                />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="20dp">

            <EditText
                android:id="@+id/password"
                android:layout_width="match_parent"
                android:layout_height="40dp"
                android:layout_marginTop="10dp"
                android:hint="密   码"
                android:paddingLeft="10dp"
                android:password="true"
                android:textColor="#ff000000"
                android:textSize="15sp"
                android:text="@={viewmodel.user.mPassWord}"
                />
        </LinearLayout>
        <Button
            android:id="@+id/login"
            android:layout_width="200dp"
            android:layout_height="wrap_content"
            android:layout_marginLeft="80dp"
            android:layout_marginTop="10dp"
            android:background="#1A73E8"
            android:text="登录"
            android:textColor="#ffffff"
            android:textSize="15sp"
            android:onClick="@{viewmodel.Login}"/>
    </LinearLayout>
</layout>

视图与数据绑定

初始化User类的数据, 完成视图与数据绑定

public class MainActivity extends AppCompatActivity {
    private ActivityMainBinding binding;
    private User user;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate( savedInstanceState );
        binding = DataBindingUtil.setContentView( this,R.layout.activity_main );
        user = new User( "admin","12345" );
        binding.setViewmodel( new ViewModel( binding,user ) );
    }
}

以上是关于登录接口实现细节分析与登录接口代码实现的主要内容,如果未能解决你的问题,请参考以下文章

Spring Security----JWT详解

结对编程总结+git使用与GitHub代码管理——by林玉俊&唐宇涵

PHP实现的注册,登录及查询用户资料功能API接口示例

Android——MVCMVPMVVM框架实现登录示例

Python随笔1《实现简单的登录接口》

Java实现微信登录