前置路由守卫:就是在路由跳转前加上自己得一些业务代码。
添加配置
- router.beforeEach((to, from, next) => {
- var path = to.path;
- if(path==="/login"){
- return next();
- }
-
- var token = sessionStorage.getItem("token");
- if(token){
- return next();
- }
- return next("/login")
- })

- <dependency>
- <groupId>org.apache.shirogroupId>
- <artifactId>shiro-spring-boot-starterartifactId>
- <version>1.7.0version>
- dependency>
- import com.ytr.system.filter.Myfilter;
- import com.ytr.system.realm.MyRealm;
- import org.apache.shiro.authc.credential.CredentialsMatcher;
- import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
- import org.apache.shiro.realm.Realm;
- import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
- import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
- import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
- import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
- import org.springframework.boot.web.servlet.FilterRegistrationBean;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
- import org.springframework.web.filter.DelegatingFilterProxy;
-
- import javax.servlet.Filter;
- import java.util.HashMap;
-
-
- /**
- * @author Yang
- * @ClassName myConfig
- * @date 2022/8/7 14:44
- */
- @Configuration
- public class ShiroConfig {
-
- /*配置shiro管理器*/
- @Bean
- public DefaultWebSecurityManager securityManager() {
- DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
- /*设置读取的自定义的relam*/
- defaultWebSecurityManager.setRealm(realm());
- return defaultWebSecurityManager;
- }
-
-
- /*创建realm配置自定义的relam*/
- @Bean
- public Realm realm() {
- MyRealm myRealm = new MyRealm();
- /*设置密码加密器 调用自定义的加密器*/
- myRealm.setCredentialsMatcher(credentialsMatcher());
- return myRealm;
- }
-
- /*设置密码加密器配置*/
- @Bean
- public CredentialsMatcher credentialsMatcher() {
- /*创建密码加密器*/
- HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
- /*设置加密形式*/
- credentialsMatcher.setHashAlgorithmName("MD5");
- /*设置加密次数*/
- credentialsMatcher.setHashIterations(1024);
- return credentialsMatcher;
- }
-
- /*创建过滤器*/
- @Bean(value = "shiroFilter")
- public ShiroFilterFactoryBean filterFactoryBean() {
- ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
- factoryBean.setSecurityManager(securityManager());
-
- //设置拦截规则
- HashMap
map = new HashMap<>(); - map.put("/system/login", "anon");
- map.put("/**", "authc");
-
- //放行Swagger2页面,需要放行这些
- map.put("/swagger-ui.html", "anon");
- map.put("/swagger/**", "anon");
- map.put("/webjars/**", "anon");
- map.put("/swagger-resources/**", "anon");
- map.put("/v2/**", "anon");
- map.put("/static/**", "anon");
- map.put("/doc.html", "anon");
- map.put("/swagger2/**", "anon");
-
- factoryBean.setFilterChainDefinitionMap(map);
-
- //设置自定义认证过滤器
- HashMap
filterMap = new HashMap(); - filterMap.put("authc", new Myfilter());
- factoryBean.setFilters(filterMap);
-
- return factoryBean;
- }
-
- @Bean //注册filter
- public FilterRegistrationBean
filterRegistrationBean() { - FilterRegistrationBean
filterRegistrationBean = new FilterRegistrationBean<>(); - filterRegistrationBean.setName("shiroFilter");
- filterRegistrationBean.setFilter(new DelegatingFilterProxy());
- filterRegistrationBean.addUrlPatterns("/*");
- return filterRegistrationBean;
- }
-
- //开启shiro注解
- @Bean
- public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
- AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
- authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
- return authorizationAttributeSourceAdvisor;
-
- }
-
- @Bean
- public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
- DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
- advisorAutoProxyCreator.setProxyTargetClass(true);
- return advisorAutoProxyCreator;
- }
-
- /* @Bean
- //LifecycleBeanPostProcessor 是管理shiro生命周期的
- //这个方法不加也可以
- public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
- return new LifecycleBeanPostProcessor();
- }*/
-
-
- }
- import com.fasterxml.jackson.databind.ObjectMapper;
-
- import com.ytr.system.vo.CommonResult;
- import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
-
- import javax.servlet.ServletRequest;
- import javax.servlet.ServletResponse;
- import java.io.PrintWriter;
-
- /**
- * @author Yang
- * @ClassName Myfilter
- * @date 2022/8/7 10:41
- */
- public class Myfilter extends FormAuthenticationFilter {
- @Override
- //未登录时进入该方法
- protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
- response.setContentType("application/json;charset=utf-8");
- PrintWriter writer = response.getWriter();
- CommonResult commonResult = new CommonResult(3000, "未登录", null);
- ObjectMapper objectMapper = new ObjectMapper();
- String json = objectMapper.writeValueAsString(commonResult);
- writer.print(json);
- writer.flush();
- writer.close();
- return false;
- }
- }
- import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
- import com.ytr.system.entity.User;
- import com.ytr.system.service.IUserService;
- import org.apache.shiro.authc.AuthenticationException;
- import org.apache.shiro.authc.AuthenticationInfo;
- import org.apache.shiro.authc.AuthenticationToken;
- import org.apache.shiro.authc.SimpleAuthenticationInfo;
- import org.apache.shiro.authz.AuthorizationInfo;
- import org.apache.shiro.authz.SimpleAuthorizationInfo;
- import org.apache.shiro.realm.AuthorizingRealm;
- import org.apache.shiro.subject.PrincipalCollection;
- import org.apache.shiro.subject.Subject;
- import org.apache.shiro.util.ByteSource;
- import org.springframework.beans.factory.annotation.Autowired;
-
- import java.util.List;
-
- /**
- * @author Yang
- * @ClassName MyRealm
- * @date 2022/8/7 14:54
- */
- public class MyRealm extends AuthorizingRealm {
-
-
- @Autowired
- private IUserService iUserService;
- /*授权方法 当执行权限校验时执行此方法*/
- @Override
- protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
-
-
- return null;
- }
-
- /*认证方法*/
- @Override
- protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
-
- /*根据token获取账号*/
- String username = (String) authenticationToken.getPrincipal();
- /*定义查询封装类,将查询的条件封装进去*/
- QueryWrapper
queryWrapper = new QueryWrapper<>(); - queryWrapper.eq("username",username);
- queryWrapper.eq("is_deleted",0);
- /*根据账号查询用户信息*/
- User one = iUserService.getOne(queryWrapper);
- if (one != null) {
- /*获取盐*/
- ByteSource byteSource = ByteSource.Util.bytes(one.getSalt());
- /*从数据库获取密码*/
- SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(one, one.getPassword(), byteSource, this.getName());
- return info;
- }
- return null;
- }
- }
- import com.fasterxml.jackson.databind.ObjectMapper;
-
- import com.ytr.system.vo.CommonResult;
- import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
-
- import javax.servlet.ServletRequest;
- import javax.servlet.ServletResponse;
- import java.io.PrintWriter;
-
- /**
- * @author Yang
- * @ClassName Myfilter
- * @date 2022/8/7 10:41
- */
- public class Myfilter extends FormAuthenticationFilter {
- @Override
- //未登录时进入该方法
- protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
- response.setContentType("application/json;charset=utf-8");
- PrintWriter writer = response.getWriter();
- CommonResult commonResult = new CommonResult(3000, "未登录", null);
- ObjectMapper objectMapper = new ObjectMapper();
- String json = objectMapper.writeValueAsString(commonResult);
- writer.print(json);
- writer.flush();
- writer.close();
- return false;
- }
- }
-
-
-

修改
- import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
- import com.ytr.system.entity.User;
- import com.ytr.system.service.IUserService;
- import com.ytr.system.vo.CommonResult;
- import com.ytr.system.vo.LoginVo;
- import io.swagger.annotations.Api;
- import io.swagger.annotations.ApiOperation;
- import org.apache.shiro.SecurityUtils;
- import org.apache.shiro.authc.UsernamePasswordToken;
- import org.apache.shiro.subject.Subject;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.data.redis.core.RedisTemplate;
- import org.springframework.data.redis.core.ValueOperations;
- import org.springframework.web.bind.annotation.*;
-
- import java.util.UUID;
- import java.util.concurrent.TimeUnit;
-
- /**
- * @author Yang
- * @ClassName LoginCon
- * @date 2022/8/8 15:30
- */
- @RestController
- @RequestMapping(value = "/system")
- @Api(tags = "登录接口类")
- public class LoginCon {
-
- @Autowired
- IUserService userService;
-
- @Autowired
- private RedisTemplate redisTemplate;
-
- @ApiOperation(value = "登录接口方法")
- @PostMapping(value = "/login")
- public CommonResult login(@RequestBody LoginVo loginVo){
- try{
- /*获取subject*/
- Subject subject = SecurityUtils.getSubject();
- /*封装用户信息*/
- UsernamePasswordToken usernamePasswordToken=new UsernamePasswordToken(loginVo.getUid(),loginVo.getUpwd());
- /*调用login方法*/
- subject.login(usernamePasswordToken);
- /*获取查询到的用户信息 */
- Object principal = subject.getPrincipal();
- //随机生成一个唯一字符串。
- String token = UUID.randomUUID().toString();
- //把该token作为redis的key value为当前登录用户信息
- ValueOperations forValue = redisTemplate.opsForValue();
- /*存值,并设置有效时间*/
- forValue.set(token,principal,24, TimeUnit.HOURS);
- return new CommonResult(2000,"登录成功",token);
- }catch (Exception e){
- return new CommonResult(5000,"登陆失败",null);
- }
- }
- }

这个跨域问题之前已经解决,这篇笔记用的就是在下面的笔记代码中修改来的,在里面已经解决了跨域问题,可这里又出现了
前后端分离
https://blog.csdn.net/weixin_43766390/article/details/126228074?spm=1001.2014.3001.5501
原因:
前端的请求被shiro得拦截器给拦截了。前端VUE发送两种请求方式,OPTIONS和http请求,
浏览器会首先发送预检请求OPTIONS请求,当OPTIONS请求通过之后,会再次发送我们当前的实际请求,所以我们要做的是让请求通过预检。
修改我们写的过滤器添加一个登录判断
- @Override
- /*这个方法返回true的话下面的未登录方法一定不会执行 */
- protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
- HttpServletRequest httpServletRequest = (HttpServletRequest) request;
- /*获取请求方式*/
- String method = httpServletRequest.getMethod();
- if(method!=null && method.equals("OPTIONS")){
- return true;
- }
-
- /*判断请求头是否携带token值*/
- String taken = httpServletRequest.getHeader("taken");
- if(taken!=null){
- return true;
- }
-
- return false;
- }

在获取token后应该再和redis中的对比,看看是不是确实存在的token

解决方案:


- @Autowired
- private RedisTemplate redisTemplate;
- /*创建过滤器*/
- @Bean(value = "shiroFilter")
- public ShiroFilterFactoryBean filterFactoryBean() {
- ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
- factoryBean.setSecurityManager(securityManager());
-
- //设置拦截规则
- HashMap
map = new HashMap<>(); - map.put("/system/login", "anon");
- map.put("/**", "authc");
-
- //放行Swagger2页面,需要放行这些
- map.put("/swagger-ui.html", "anon");
- map.put("/swagger/**", "anon");
- map.put("/webjars/**", "anon");
- map.put("/swagger-resources/**", "anon");
- map.put("/v2/**", "anon");
- map.put("/static/**", "anon");
- map.put("/doc.html", "anon");
- map.put("/swagger2/**", "anon");
-
- factoryBean.setFilterChainDefinitionMap(map);
-
- //设置自定义认证过滤器(过滤未登录的)
- HashMap
filterMap = new HashMap(); - filterMap.put("authc", new Myfilter(redisTemplate));
- factoryBean.setFilters(filterMap);
-
- return factoryBean;
- }
过滤器
- import com.fasterxml.jackson.databind.ObjectMapper;
-
- import com.ytr.system.vo.CommonResult;
- import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
- import org.springframework.data.redis.core.RedisTemplate;
-
- import javax.servlet.ServletRequest;
- import javax.servlet.ServletResponse;
- import javax.servlet.http.HttpServletRequest;
- import java.io.PrintWriter;
-
- /**
- * @author Yang
- * @ClassName Myfilter
- * @date 2022/8/7 10:41
- */
- public class Myfilter extends FormAuthenticationFilter {
-
- private RedisTemplate redisTemplate;
-
- /*定义构造函数*/
- public Myfilter(RedisTemplate redisTemplate){
- this.redisTemplate=redisTemplate;
- }
-
- @Override
- /*这个方法返回true的话下面的未登录方法一定不会执行 */
- protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
- HttpServletRequest httpServletRequest = (HttpServletRequest) request;
- /*获取请求方式*/
- String method = httpServletRequest.getMethod();
- if(method!=null && method.equals("OPTIONS")){
- return true;
- }
-
- /*判断请求头是否携带token值*/
- String taken = httpServletRequest.getHeader("token");
- System.out.println(taken);
- if(taken!=null && redisTemplate.hasKey(taken)){
- System.out.println(taken);
-
- return true;
- }
-
- return false;
- }
-
- @Override
- //未登录时进入该方法
- protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
- response.setContentType("application/json;charset=utf-8");
- PrintWriter writer = response.getWriter();
- CommonResult commonResult = new CommonResult(3000, "未登录", null);
- ObjectMapper objectMapper = new ObjectMapper();
- String json = objectMapper.writeValueAsString(commonResult);
- writer.print(json);
- writer.flush();
- writer.close();
- return false;
- }
- }
注意




- /*退出*/
- @GetMapping("/quit")
- public CommonResult quit(HttpServletRequest request){
- /*从前端请求中获取token*/
- String token = request.getHeader("token");
- /*对比数据库查看有没有这个token*/
- if(redisTemplate.hasKey(token)){
- /*删除*/
- redisTemplate.delete(token);
- return new CommonResult(2000,"退出成功",null);
- }
- return new CommonResult(5000,"退出失败",null);
- }
-
- import com.ytr.system.entity.Permission;
- import com.ytr.system.entity.User;
- import com.ytr.system.mapper.PermissionMapper;
- import com.ytr.system.service.IPermissionService;
- import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
- import com.ytr.system.vo.CommonResult;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.data.redis.core.RedisTemplate;
- import org.springframework.data.redis.core.ValueOperations;
- import org.springframework.stereotype.Service;
-
- import java.util.ArrayList;
- import java.util.List;
-
- /**
- *
- * 权限 服务实现类
- *
- *
- * @author ytr
- * @since 2022-08-08
- */
- @Service
- public class PermissionServiceImpl extends ServiceImpl
implements IPermissionService { - @Autowired
- protected RedisTemplate redisTemplate;
-
- @Autowired
- protected PermissionMapper permissionMapper;
-
- @Override
- public CommonResult findPermissionByuserId(String token) {
- //根据token获取用户信息
- ValueOperations valueOperations = redisTemplate.opsForValue();
- User user = (User) valueOperations.get(token);
- String id = user.getId();
- /*根据用户id查询所具有的菜单*/
- List
permissions = permissionMapper.selMenuByUserId(id); -
- //设置层级关系
- List
firstMenus = new ArrayList<>(); - for (Permission first : permissions) {
- //int
- if (first.getPid().equals("1")) {
- firstMenus.add(first);
- }
- }
-
-
- //为一级菜单设置二级菜单
- for (Permission first : firstMenus) {
- //根据一级菜单id 查询 该菜单得二级菜单。如果出现不确定有几级菜单 那么我们可以使用方法得递归调用
- first.setChildren(findChildren(permissions, first.getId()));
-
- }
- System.out.println("打印firstMenus"+firstMenus);
- return new CommonResult(2000,"查询成功",firstMenus);
- }
-
- //方法递归
- private List
findChildren(List permissionList, String id) { - List
children = new ArrayList<>(); - for (Permission p : permissionList) {
- if (p.getPid().equals(id)) {
- children.add(p);
- }
- }
-
- for (Permission child : children) {
- child.setChildren(findChildren(permissionList, child.getId()));
- }
- return children;
- }
- }