最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

SpringBoot實(shí)現(xiàn)登錄攔截器超詳細(xì)教程分享

 更新時(shí)間:2023年02月16日 11:49:19   作者:Qgchun.  
對(duì)于管理系統(tǒng)或其他需要用戶登錄的系統(tǒng),登錄驗(yàn)證都是必不可少的環(huán)節(jié),尤其在?SpringBoot?開發(fā)的項(xiàng)目中。本文為大家準(zhǔn)備了超詳細(xì)的SpringBoot實(shí)現(xiàn)登錄攔截器方法,快收藏一波吧

SpringBoot實(shí)現(xiàn)登錄攔截器

對(duì)于管理系統(tǒng)或其他需要用戶登錄的系統(tǒng),登錄驗(yàn)證都是必不可少的環(huán)節(jié),在 SpringBoot 開發(fā)的項(xiàng)目中,通過實(shí)現(xiàn)攔截器來實(shí)現(xiàn)用戶登錄攔截并驗(yàn)證。

SpringBoot 實(shí)現(xiàn)登錄攔截的原理

SpringBoot 通過實(shí)現(xiàn)HandlerInterceptor接口實(shí)現(xiàn)攔截器,通過實(shí)現(xiàn)WebMvcConfigurer接口實(shí)現(xiàn)一個(gè)配置類,在配置類中注入攔截器,最后再通過 @Configuration 注解注入配置.

1.實(shí)現(xiàn)HandlerInterceptor接口

實(shí)現(xiàn)HandlerInterceptor接口需要實(shí)現(xiàn) 3 個(gè)方法:preHandle、postHandle、afterCompletion.

3 個(gè)方法各自的功能如下:

public class UserLoginInterceptor implements HandlerInterceptor {

    /***
     * 在請(qǐng)求處理之前進(jìn)行調(diào)用(Controller方法調(diào)用之前)
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        System.out.println("執(zhí)行了攔截器的preHandle方法");
        try {
            HttpSession session = request.getSession();
            //統(tǒng)一攔截(查詢當(dāng)前session是否存在user)(這里user會(huì)在每次登錄成功后,寫入session)
            User user = (User) session.getAttribute(USER_LOGIN_STATE);
            if (user != null) {
                return true;
            }
            //重定向登錄頁面
            response.sendRedirect(request.getContextPath() + "/user/login");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
        //如果設(shè)置為false時(shí),被請(qǐng)求時(shí),攔截器執(zhí)行到此處將不會(huì)繼續(xù)操作
        //如果設(shè)置為true時(shí),請(qǐng)求將會(huì)繼續(xù)執(zhí)行后面的操作
    }

    /***
     * 請(qǐng)求處理之后進(jìn)行調(diào)用,但是在視圖被渲染之前(Controller方法調(diào)用之后)
     */
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("執(zhí)行了攔截器的postHandle方法");
    }

    /***
     * 整個(gè)請(qǐng)求結(jié)束之后被調(diào)用,也就是在DispatchServlet渲染了對(duì)應(yīng)的視圖之后執(zhí)行(主要用于進(jìn)行資源清理工作)
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("執(zhí)行了攔截器的afterCompletion方法");
    }
}

preHandle在 Controller 之前執(zhí)行,因此攔截器的功能主要就是在這個(gè)部分實(shí)現(xiàn):

1.檢查 session 中是否有user對(duì)象存在;

2.如果存在,就返回true,那么 Controller 就會(huì)繼續(xù)后面的操作;

3.如果不存在,就會(huì)重定向到登錄界面

就是通過這個(gè)攔截器,使得 Controller 在執(zhí)行之前,都執(zhí)行一遍preHandle.

2.實(shí)現(xiàn)WebMvcConfigurer接口,注冊(cè)攔截器

實(shí)現(xiàn)WebMvcConfigurer接口來實(shí)現(xiàn)一個(gè)配置類,將上面實(shí)現(xiàn)的攔截器的一個(gè)對(duì)象注冊(cè)到這個(gè)配置類中.

@Configuration
public class LoginConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //注冊(cè)TestInterceptor攔截器
        InterceptorRegistration registration = registry.addInterceptor(new UserLoginInterceptor());
        //所有路徑都被攔截
        registration.addPathPatterns("/**");
        //添加不攔截路徑
        registration.excludePathPatterns(
                "/user/login",
                "/user/register",
                "/**/*.html",
                "/**/*.js",
                "/**/*.css"
        );
    }
}

將攔截器注冊(cè)到了攔截器列表中,并且指明了攔截哪些訪問路徑,不攔截哪些訪問路徑,不攔截哪些資源文件;最后再以 @Configuration 注解將配置注入。

3.保持登錄狀態(tài)

只需一次登錄,如果登錄過,下一次再訪問的時(shí)候就無需再次進(jìn)行登錄攔截,可以直接訪問網(wǎng)站里面的內(nèi)容了。

在正確登錄之后,就將user保存到session中,再次訪問頁面的時(shí)候,登錄攔截器就可以找到這個(gè)user對(duì)象,就不需要再次攔截到登錄界面了.

UserController

@Slf4j
@RestController
@RequestMapping("/user")
public class UserController {

    @Resource
    private UserService userService;
    /**
     * 發(fā)送郵箱驗(yàn)證碼
     * @return
     */
    @PostMapping("/sendCode")
    public BaseResponse<String> sendCode(@RequestBody String email) {
        // 發(fā)送短信驗(yàn)證碼并保存驗(yàn)證碼
        String code = userService.sendCode(email);
        return ResultUtils.success(code);
    }

    /**
     * 注冊(cè)功能
     * @param userRegisterRequest
     * @return
     */
    @PostMapping("/register")
    public BaseResponse<Long> register(@RequestBody UserRegisterRequest userRegisterRequest){
        if(userRegisterRequest==null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"請(qǐng)求參數(shù)為空");
        }
        String email = userRegisterRequest.getEmail();
        String userpassword = userRegisterRequest.getUserPassword();
        String checkpassword = userRegisterRequest.getCheckPassword();
        String userName = userRegisterRequest.getName();
        String code = userRegisterRequest.getCode();
        if(StringUtils.isAnyBlank(email,userpassword,checkpassword,userName,code)){
            return null;
        }
        long result = userService.userRegister(email, userpassword, checkpassword, userName, code);
        return ResultUtils.success(result);
    }

    /**
     * 登錄功能
     * @param userLoginRequest
     * @param request
     * @return
     */
    @PostMapping("/login")
    public BaseResponse<User> userdoLogin(@RequestBody UserLoginRequest userLoginRequest, HttpServletRequest request){
        if(userLoginRequest==null){
            throw new BusinessException(ErrorCode.PARAMS_ERROR,"請(qǐng)求參數(shù)為空");
        }
        String email = userLoginRequest.getEmail();
        String password = userLoginRequest.getPassword();
        if (StringUtils.isAnyBlank(email,password)){
            return null;
        }
        User result = userService.userdoLogin(email, password,request);
        return ResultUtils.success(result);
    }

    /**
     * 登出功能
     * @param request
     * @return
     */
    @PostMapping("/logout")
    public BaseResponse<Integer> userlogout(HttpServletRequest request){
        if(request==null){
            throw new BusinessException(ErrorCode.NOT_LOGIN,"該用戶沒有登錄");
        }
        int result = userService.userLogout(request);
        return ResultUtils.success(result);
    }

UserService

public interface UserService extends IService<User> {
    /**
     * 發(fā)送驗(yàn)證碼
     * @param email
     * @return
     */
    String sendCode(String email);

    /**
     * 用戶注冊(cè)
     *
     * @param userEmail 用戶郵箱
     * @param userPassword 用戶密碼
     * @param checkPassword 用戶檢驗(yàn)密碼
     *
     * @return
     */
    long userRegister(String userEmail,String userPassword,String checkPassword,String userName,String code);

    /**
     * 用戶登錄
     * @param email
     * @param password
     * @param request
     * @return
     */
    User userdoLogin(String email, String password, HttpServletRequest request);
     /**
     * 用戶登出
     * @param request
     * @return
     */
    int userLogout(HttpServletRequest request);

UserServiceImpl

@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper,User>
        implements UserService{
    @Resource
    private UserMapper userMapper;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    public static final String SALT = "qgc";

    /**
     * 發(fā)送郵箱驗(yàn)證碼
     * @param email
     * @return
     */
    @Override
    public String sendCode(String email) {
        //1.生成驗(yàn)證碼
        String code = RandomUtil.randomNumbers(6);
        //2.保存驗(yàn)證碼到redis中  //set key value ex
        stringRedisTemplate.opsForValue().set(code + LOGIN_CODE_KEY, code, LOGIN_CODE_TTL, TimeUnit.MINUTES);
        //3.發(fā)送驗(yàn)證碼
        log.debug("發(fā)送郵箱驗(yàn)證碼成功,驗(yàn)證碼:{}", code);
        return code;
    }

    /**
     * 用戶注冊(cè)
     * @param email 郵箱
     * @param userPassword 用戶密碼
     * @param checkPassword 用戶檢驗(yàn)密碼
     *
     * @param userName 用戶名字
     * @param code 驗(yàn)證碼
     * @return
     */
    @Override
    public long userRegister(String email,String userPassword,String checkPassword,String userName,String code) {
        //1.校驗(yàn)
        if(StringUtils.isAnyBlank(email,userPassword,checkPassword,userName,code)){
            throw new BusinessException(PARAMS_ERROR,"請(qǐng)求參數(shù)為空");
        }
        if(userPassword.length() < 8 ||checkPassword.length() < 8){
            throw new BusinessException(PARAMS_ERROR,"密碼小于8位");
        }
        if(userName.length()> 10){
            throw new BusinessException(PARAMS_ERROR,"名字大于10位");
        }
        if(code.length() != 6){
            throw new BusinessException(PARAMS_ERROR,"驗(yàn)證碼長度應(yīng)該為6位");
        }
        //密碼和校驗(yàn)密碼相同
        if(!userPassword.equals(checkPassword)){
            throw new BusinessException(PARAMS_ERROR);
        }
        //賬戶郵箱不能重復(fù)
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("email",email);
        Long count = userMapper.selectCount(queryWrapper);
        if (count>0){
            throw new BusinessException(PARAMS_ERROR);
        }
        //昵稱不能重復(fù)
        queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name",userName);
        count = userMapper.selectCount(queryWrapper);
        if (count>0){
            throw new BusinessException(PARAMS_ERROR);
        }
        //判斷驗(yàn)證碼是否正確
        String cachecode = stringRedisTemplate.opsForValue().get(code + LOGIN_CODE_KEY);
        if(cachecode==null||!cachecode.equals(code)){
            //不一致,報(bào)錯(cuò)
            throw new BusinessException(PARAMS_ERROR);
        }
        //2.加密
        String encryptPassword = DigestUtils.md5DigestAsHex((SALT + userPassword).getBytes(StandardCharsets.UTF_8));
        //3.插入數(shù)據(jù)
        User user = new User();
        user.setEmail(email);
        user.setPassword(encryptPassword);
        user.setName(userName);
        boolean res = this.save(user);
        if(!res){
            return -1;
        }
        return user.getId();
    }

    /**
     * 用戶登錄
     * @param email
     * @param password
     * @param request
     * @return
     */
    @Override
    public User userdoLogin(String email, String password,HttpServletRequest request) {
        //1.校驗(yàn)
        if(StringUtils.isAnyBlank(email,password)){
            return null;
        }
        if (RegexUtils.isEmailInvalid(email)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "郵箱格式錯(cuò)誤");
        }
        if(password.length() < 8 ){
            return null;
        }
        //2.加密
        String encryptPassword = DigestUtils.md5DigestAsHex((SALT + password).getBytes(StandardCharsets.UTF_8));
        //判斷賬戶是否存在
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("email",email);
        queryWrapper.eq("password",encryptPassword);
        User user = userMapper.selectOne(queryWrapper);
        if(user==null){
            log.info("user login failed");
            return null;
        }
        //用戶脫敏
        User safeUser = getSafeUser(user);
        //4.記錄用戶登錄狀態(tài)
        request.getSession().setAttribute(USER_LOGIN_STATE,safeUser);
        return safeUser;
    }
    /**
     * 登出功能
     * @param request
     * @return
     */
    @Override
    public int userLogout(HttpServletRequest request) {
        request.getSession().removeAttribute(USER_LOGIN_STATE);
        return 1;
    }

springboot攔截器excludePathPatterns方法不生效的坑與解決方法

最近在springboot項(xiàng)目里需要配置個(gè)攔截器白名單,用excludePathPatterns方法配置些url,讓攔截器不攔截這些url;

本來這是個(gè)很簡單的東西,但是配置完畢后就是沒有生效;

在此記錄下這個(gè)坑的解決方法。

問題

1.例如,想讓以下url不被攔截器攔截:

http://localhost:8080/api/department/add

2.攔截器配置代碼如下:

@Configuration
public class LoginConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //注冊(cè)TestInterceptor攔截器
        InterceptorRegistration registration = registry.addInterceptor(new UserLoginInterceptor());
        //所有路徑都被攔截
        registration.addPathPatterns("/**");
        //添加不攔截路徑
        registration.excludePathPatterns(
                "/user/login",
                "/user/register",
                "/api/department/add"
                "/**/*.html",
                "/**/*.js",
                "/**/*.css"
        );
    }
}

3.看起來沒有問題,但是當(dāng)訪問上方url的時(shí)候,還是會(huì)被攔截器攔截,就很坑。

解決方法

1.通過排查發(fā)現(xiàn),原來,在application.yml中,是這樣配置的:

server:
  port: 8080
  servlet:
    context-path: /api

2.所以,還是攔截器的url配置錯(cuò)了,想不攔截的話,需要這樣配置:

@Configuration
public class LoginConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        //注冊(cè)TestInterceptor攔截器
        InterceptorRegistration registration = registry.addInterceptor(new UserLoginInterceptor());
        //所有路徑都被攔截
        registration.addPathPatterns("/**");
        //添加不攔截路徑
        registration.excludePathPatterns(
                "/user/login",
                "/user/register",
                "/department/add"
                "/**/*.html",
                "/**/*.js",
                "/**/*.css"
        );
    }
}

3.這樣,訪問這個(gè)url,才能不被攔截器攔截:

http://localhost:8080/survey-project/download/special

總結(jié)

1.配置攔截器時(shí),如果excludePathPatterns沒有生效,可能是url配置有問題。

2.可以檢查下application.yml的context-path,或者其它類似的地方,配置攔截器的url不應(yīng)該包含這些路徑,只要從Controller的路徑開始配置即可。

擴(kuò)展

使用response對(duì)象的sendRedirect()方法將用戶的請(qǐng)求重定向到指定路徑,這個(gè)路徑由request對(duì)象的getContextPath()方法獲取,再加上字符串 “/” 組成。getContextPath()方法返回當(dāng)前web應(yīng)用程序的上下文路徑,此處加的字符串路徑也是從Controller的路徑開始配置即可

“/user/login”

 //重定向登錄頁面
 response.sendRedirect(request.getContextPath() + "/user/login");

會(huì)被重定向到

http://127.0.0.1:8080/user/login

“/login”

 //重定向登錄頁面
 response.sendRedirect(request.getContextPath() + "/login");

http://127.0.0.1:8080/login

"/user/login"也是從Controller的路徑開始配置

以上就是SpringBoot實(shí)現(xiàn)登錄攔截器超詳細(xì)教程分享的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot登錄攔截器的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論

湖口县| 湾仔区| 隆尧县| 游戏| 五常市| 尼木县| 桐梓县| 北海市| 即墨市| 江城| 宣威市| 专栏| 远安县| 城口县| 长治县| 噶尔县| 丁青县| 牡丹江市| 安仁县| 克山县| 丰台区| 龙岩市| 肇州县| 深水埗区| 满城县| 石景山区| 阳谷县| 斗六市| 五大连池市| 英山县| 英德市| 乌拉特后旗| 三门峡市| 凤山市| 宝兴县| 分宜县| 黑山县| 庆安县| 波密县| 定远县| 革吉县|