欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

spring boot vue 前后端分离 shiro 认证失败

程序员文章站 2022-06-13 15:31:59
...

shiro 认证失败 ,但是用户有权限

点击看那个博客

后端代码

usersController

package com.graduate.twentyone.controller;

import com.graduate.twentyone.diman.RestDate;
import com.graduate.twentyone.diman.Users;
import org.apache.catalina.User;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.Map;

@Controller
@ResponseBody
@CrossOrigin
public class UsersController {

/***
*@methodName userslogin
*@方法功能描述
*@params
* @param users
*@return com.graduate.twentyone.diman.RestDate
*@exception
*@author $風~$
*@Date 2021/3/22
*/
@RequestMapping(value = "userlogin" ,method = RequestMethod.POST)
// @GetMapping("/userlogin")
public RestDate userslogin(@RequestBody Users users) {
String uname = users.getUname();
String pwd = users.getPwd();
System.out.println( " 222 uname " + uname);
System.out.println(" 333 pwd " + pwd);

Subject subject = SecurityUtils.getSubject();

RestDate<Object> restDate = new RestDate<>(800, "error", "返回的数据");
String authToken1 = (String) subject.getSession().getId();

System.out.println(authToken1+" authtoken");
Map map = new HashMap();
map.put("authToken",authToken1);
try {
subject.login(new UsernamePasswordToken(uname, pwd));
} catch (IncorrectCredentialsException incorrectCredentialsException) {
restDate = new RestDate<>(2, "密码错误", "返回的数据");
return restDate;
} catch (UnknownAccountException UnknownAccountException) {
restDate = new RestDate<>(1, "账号错误", "返回的数据");
return restDate;
} catch (NullPointerException nullPointerException) {
restDate = new RestDate<>(0, "未输入信息", "返回的数据");
return restDate;
}
if (subject.isAuthenticated()) {
restDate = new RestDate<>(-1, "success",map);
return restDate;
}

return restDate;
}

}

foodController

package com.graduate.twentyone.controller;

import com.graduate.twentyone.diman.Food;
import com.graduate.twentyone.diman.RestDate;
import com.graduate.twentyone.service.FoodService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.security.auth.Subject;
import java.sql.SQLOutput;
import java.util.List;
import java.util.Map;

@RestController
@CrossOrigin
public class FoodController {
@Autowired
FoodService foodService;
// @RequiresUser
// @RequiresAuthentication
// @RequiresRoles("admin")
@RequiresPermissions("food:add")
@RequestMapping(value = "/addfood",method = RequestMethod.POST)
public RestDate addfood(@RequestBody Food food){
Integer addfood = foodService.addfood(food);
RestDate restDate = new RestDate(500,"发生未知错误","返回的数据");
if (addfood == 1){
restDate = new RestDate(-1,"成功","返回的数据");
}
return restDate;
}

@RequiresPermissions("food:update")
@RequestMapping(value = "/updatefood",method = RequestMethod.POST)
public RestDate updatefood(@RequestBody Food food){
Integer updatefood = foodService.updatefood(food);
RestDate restDate = new RestDate(500,"发生未知错误","返回的数据");
if (updatefood == 1){
restDate = new RestDate(-1,"成功","返回的数据");
}
return restDate;
}
@RequiresPermissions("food:delete")
@RequestMapping(value = "/deletefood",method = RequestMethod.POST)
public RestDate deletefood(@RequestBody Food food){
food.setStatus(0);
Integer updatefood = foodService.updatefood(food);
RestDate restDate = new RestDate(500,"发生未知错误","返回的数据");
if (updatefood == 1){
restDate = new RestDate(-1,"成功","返回的数据");
}
return restDate;
}

@RequestMapping(value = "/selectfood",method = RequestMethod.POST)
@RequiresPermissions("food:select")
// @GetMapping("/selectfood")
public RestDate selectfood(){
System.out.println("selectfood");
System.out.println(SecurityUtils.getSubject().isAuthenticated());

boolean permitted = SecurityUtils.getSubject().isPermitted("food:select");
System.out.println("此处权限food:select为:"+permitted);

List<Food> selectfood = foodService.selectfood();
RestDate restDate = new RestDate(500,"发生未知错误",selectfood);
if (selectfood.size()>=0){
restDate = new RestDate(-1,"food 查询成功","返回的数据");
}
return restDate;
}

}

MyRealm

package com.graduate.twentyone.util.shiro;

import com.graduate.twentyone.diman.Promission;
import com.graduate.twentyone.diman.Users;
import com.graduate.twentyone.mapper.UsersMapper;
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.springframework.beans.factory.annotation.Autowired;

import java.util.List;


public class MyRealm extends AuthorizingRealm {

@Autowired
UsersMapper usersMapper;


//获取当前用户的身份
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String uname = authenticationToken.getPrincipal().toString();


// 通过用户名查找该用户的信息
Users user = usersMapper.login(uname);
System.out.println("asdsdsdsdsdsd:"+user);
//返回认证信息对象
if (user != null) {
AuthenticationInfo info = new SimpleAuthenticationInfo(user.getUname(), user.getPwd(), "myRealm");
return info;

}
return null;
}


// 获取当前用户的所有权限
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
// 获取权限信息
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
System.out.println("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");

// 获取用户名
String uname = (String) principalCollection.getPrimaryPrincipal();
// 获取用户的身份
String loginrname = usersMapper.loginrname(uname);
// 添加进去
info.addRole(loginrname);

// 获取用户的权限
List<Promission> loginpro = usersMapper.loginpro(uname);
// 遍历添加
for (int i = 0; i < loginpro.size(); i++) {
System.out.println("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
System.out.println(loginpro.get(i).getPname());
info.addStringPermission(loginpro.get(i).getPname());
}
return info;
}

}

ShiroConfig

package com.graduate.twentyone.util.shiro;


import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ShiroConfig {

@Bean("realm")
public MyRealm getRealm() {
return new MyRealm();
}

@Bean("securityManager")
public DefaultWebSecurityManager getSecurityManager(MyRealm realm,DefaultWebSessionManager sessionManager) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(realm);
securityManager.setSessionManager(sessionManager);
return securityManager;
}


@Bean
public DefaultWebSessionManager getDefaultWebSessionManager(){
// 这个是另一个文件的
return new ShiroSession();
}

@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean shiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//注入核心安全管理器
shiroFilterFactoryBean.setSecurityManager(securityManager);

return shiroFilterFactoryBean;
}


//开启对shior注解的支持
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(DefaultWebSecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
return advisor;
}


@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
proxyCreator.setProxyTargetClass(true);
return proxyCreator;
}

@Bean
public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor(){
return new LifecycleBeanPostProcessor();
}

}

ShiroSession

package com.graduate.twentyone.util.shiro;


import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.util.StringUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.Serializable;

public class ShiroSession extends DefaultWebSessionManager {

/**
* 定义的请求头中使用的标记key,用来传递 token
*/
private static final String AUTH_TOKEN = "authToken";
private static final String REFERENCED_SESSION_ID_SOURCE = "Stateless request";

public ShiroSession() {
super();
//设置 shiro session 失效时间,默认为30分钟,这里现在设置为15分钟
setGlobalSessionTimeout(MILLIS_PER_MINUTE * 15);
}

/**
* 获取sessionId,原本是根据sessionKey来获取一个sessionId
* 重写的部分多了一个把获取到的token设置到request的部分。这是因为app调用登陆接口的时候,是没有token的,登陆成功后,产生了token,我们把它放到request中,返回结
* 果给客户端的时候,把它从request中取出来,并且传递给客户端,客户端每次带着这个token过来,就相当于是浏览器的cookie的作用,也就能维护会话了
* @param request ServletRequest
* @param response ServletResponse
* @return Serializable
*/
@Override
protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
//获取请求头中的 AUTH_TOKEN 的值,如果请求头中有 AUTH_TOKEN 则其值为sessionId。shiro就是通过sessionId 来控制的

System.out.println("ShiroSession");

String sessionId = WebUtils.toHttp(request).getHeader("AUTH_TOKEN");
System.out.println(sessionId);
if (StringUtils.isEmpty(sessionId)){
//如果没有携带id参数则按照父类的方式在cookie进行获取sessionId
return super.getSessionId(request, response);

} else {
//请求头中如果有 authToken, 则其值为sessionId
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, REFERENCED_SESSION_ID_SOURCE);
//sessionId
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, sessionId);
request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
return sessionId;
}
}
}

————————————————————————————————————————————————————————————————————
前端代码

log.js

import request from '../utils/request';

export const login = (data) => {
    return request({
        url: '/userlogin',
        method: 'post', 
        data:data , 
    });
};

登录vue

methods: {
    submitForm() {
        var that = this;
        this.$refs.login.validate(valid => {
            if (valid) {
                var uname = that.param.username;
                var pwd = that.param.password;
                var ddd = JSON.stringify({
                    // 参数
                    uname,
                    pwd
                });
                this.userlogin(ddd);
            } else {
                that.$message.error('请输入账号和密码');
                console.log('error submit!!');
                return false;
            }
        });
    },
    userlogin(ddd) {
        var that = this;
        console.log('userlogin');
        login(ddd)
            .then(res => {
                console.log(res);
                if (res.code == -1) {
                    that.$message.success('登录成功');

//设置authToken 在本地存储 ( 这一行的上下块是一个整体)

                    localStorage.setItem("authToken",res.data.authToken)
                    localStorage.setItem('ms_username', this.param.username);
                    that.$router.push('/');
                } else if (res.code == 1) {
                    that.$message.error('账号错误');
                    console.log('error submit!!');
                    return false;
                } else if (res.code == 2) {
                    this.$message.error('密码错误');
                    console.log('error submit!!');
                    return false;
                }
            })

            .catch(res => {});
    }
}

request.js

import axios from 'axios';

// axios.defaults.withCredentials = true;

const service = axios.create({
    // process.env.NODE_ENV === 'development' 来判断是否开发环境
    // easy-mock服务挂了,暂时不使用了
    // baseURL: 'https://www.easy-mock.com/mock/592501a391470c0ac1fab128',
    baseURL: 'http://localhost:8080',
    headers: {'Content-Type': 'application/json'},
    // withCredentials: true,
    timeout: 5000
});

service.interceptors.request.use(
    config => {
        console.log(config.url)
        console.log(localStorage.getItem('authToken'))
    // 给每个请求都加上token请求头 || config.url === '/checkLogin' && (localStorage.getItem('token') != null)
    if (config.url !== '/userlogin') {
        if (localStorage.getItem('authToken')) {
        //   config.headers.token = localStorage.getItem('token');

在请求头设置AUTH_TOKEN的值
后端会获取这个值
          config.headers.AUTH_TOKEN =localStorage.getItem('authToken');
          console.log(config.headers.AUTH_TOKEN)
        } else {
          this.$router.push('/');
        }
      }
      return config;
    },
    error => {
        console.log(error);
        return Promise.reject();
    }
);

service.interceptors.response.use(
    response => {
        if (response.status === 200) {
            return response.data;
        } else {
            Promise.reject();
        }
    },
    error => {
        console.log(error);
        return Promise.reject();
    }
);


export default service;
相关标签: shiro java vue.js