前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringBoot使用Security认证框架(2.使用)

SpringBoot使用Security认证框架(2.使用)

作者头像
贫困的蚊子
发布2023-08-10 11:27:15
1970
发布2023-08-10 11:27:15
举报
文章被收录于专栏:贫困的蚊子

前言

需要的工具类,请前往:https://cloud.tencent.com/developer/article/2311121

本文章是使用方法,数据库查询使用的是mybatis-plus

mybatis-plus依赖

代码语言:javascript
复制
<dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.3.1.tmp</version>
        </dependency>

为什么mybatis-plus依赖要在这里写?

因为:

  1. 如果你的公司不允许使用mybatis-plus,而使用的是mybatis,那么下面代码,只能对你仅供参考了…
  2. 你只能参考,用mybatis自已写一个

开始

注意:我的包名叫com.zb,凡是报错的类,记得把包换成你的包

1.UserService里面有一个方法:根据用户名和密码查询,返回token

注意:不要想着直接写自已登录的Service里面,不行,因为下面要实现一个类叫UserDetailsService,你自已登录的Service里面无法同时实现2个

代码语言:javascript
复制
     String login(String username, String passwd);

2.UserDetailServiceImpl继承UserDetailsService

实现public UserDetails loadUserByUsername方法,Security会自动找谁实现了,然后获取信息,注意看注释

代码:

代码语言:javascript
复制
package com.zb.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zb.entity.LoginUser;
import com.zb.entity.Menu;
import com.zb.entity.User;
import com.zb.mapper.MenuMapper;
import com.zb.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.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class UserDetailServiceImpl implements UserDetailsService {
    @Autowired
    private UserMapper userMapper;

 	//权限认证表,不需要权限直接删除即可
    @Autowired
    private MenuMapper menuMapper;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        System.out.println("2.进入访问数据库的UserDetailServiceImpl服务类中...");
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("nick_name", username);
        //根据用户名查询用户信息
        User user = userMapper.selectOne(queryWrapper);
        
        //权限认证,如不需要权限搞权限,直接删除即可
        //拿用户名 查用户权限等信息
        List<Menu> query = menuMapper.query(user.getId().toString());
        //读取query里面权限信息(Perms参数),将信息存入list
        List<String> list = query.stream().map(menu -> {
            return menu.getPerms();
        }).collect(Collectors.toList());
			//权限认证,如不需要权限搞权限,删到这里

        if (user != null) {
            //将用户信息,权限信息放入LoginUser
            //如不要权限认证,要把下面list参数删除
            //然后去LoginUser类,24行和31行,删的东西如下:
            //LoginUser(AdminEntity user, List<String> powers)方法,删除List<String> powers参数
            //Collection<? extends GrantedAuthority> getAuthorities()直接把这个方法返回null即可
            return new LoginUser(user, list);
        }
        return null;
    }
}

3.UserServiceImpl继承自已的UserService,实现自已的login方法

注意:看42-45行

代码语言:javascript
复制
package com.zb.service.impl;

import com.alibaba.fastjson.JSON;
import com.zb.config.JwtUtil;
import com.zb.entity.LoginUser;
import com.zb.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private RedisTemplate redisTemplate;


    @Autowired
    //发起验证,此方法已经实例化
    private AuthenticationManager authenticationManager;

    @Override
    public String login(String username, String passwd) {
        //使用密码器,并且告诉密码器登录的账号密码
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
                new UsernamePasswordAuthenticationToken(username, passwd);
        //告诉验证起,本次登录使用的是密码器验证
        //这里会调用:实现UserDetailsService接口的UserDetails类 loadUserByUsername的方法
        //本意就是已经查出数据了
        Authentication authenticate = authenticationManager
                .authenticate(usernamePasswordAuthenticationToken);

        if (ObjectUtils.isEmpty(authenticate)) {
            return "登陆失败";
        }
        System.out.println("3.登陆成功信息");
        //获取数据,转成LoginUser对象
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
        //拿出用户名,生成token
        String token = JwtUtil.createJWT(loginUser.getUser().getNickName());
        //将用户名和用户信息存入redis
        redisTemplate.boundValueOps("token:" + loginUser.getUser().getNickName()).set(JSON.toJSONString(loginUser));
        return token;
    }
}

4.Controller实现刚开始创建UserService方法即可,它会返回一个token,普通方法必须传入token,否则会被拦截

代码语言:javascript
复制
package com.zb.controller;

import com.zb.entity.LoginUser;
import com.zb.entity.User;
import com.zb.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

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

    @Autowired
    private UserService userService;

    @Autowired
    private RedisTemplate redisTemplate;

    @PostMapping("/login")
    public String login(@RequestParam("username") String username, @RequestParam("passwd") String passwd) {
        return userService.login(username, passwd);
    }

    @GetMapping("/info")
    public User info() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        return loginUser.getUser();
    }

    @GetMapping("/exit")
    public String exit() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        String key = "token:" + loginUser.getUser().getNickName();
        redisTemplate.delete(key);
        return "success";
    }

    @GetMapping("/testok")
    public String tsetok(@RequestHeader String token){
        System.out.println("这是一个普通方法");
        return "这是一个普通方法";
    }

}

5.权限拦截,使用@PreAuthorize(“”)注解,里面填的是存放LoginUser类里面查出来的powers权限名字

如果不要权限认证,这里就不用看了

代码语言:javascript
复制
package com.zb.controller;

import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

    @GetMapping("/show")
   @PreAuthorize("hasAuthority('book:search') or hasAuthority('book:get')")
    public String show() {
        System.out.println("============>");
        return "hello";
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-03-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 开始
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档