vue+SpringBoot+shrio(实现前后端分离,拦截器功能,解决跨域)

shiro权限配置

package com.cdz.demo0216yiguo.config;

import com.cdz.demo0216yiguo.realm.UserRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
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.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import java.util.LinkedHashMap;
import java.util.Map;

/**
 * shiro的配置类
 * @Configuration 用于定义配置类,该类的各个方法返回各种对象实现系统的配置
 */

@Configuration
public class ShiroConfig {

    /**
     * 缓存配置
     */
    @Bean(name = "ehCacheManager")
    @DependsOn("lifecycleBeanPostProcessor")
    public EhCacheManager ehCacheManager(){
        EhCacheManager ehCacheManager = new EhCacheManager();
        return ehCacheManager;
    }

    /**
     * 返回自定义会话管理器
     * @return
     */
    @Bean
    public SessionManager sessionManager(){
        return new ShiroSessionManager();
    }

    //加入spring的容器,自动配置
    @Bean
    public HashedCredentialsMatcher hashedCredentialsMatcher(){
        //密码匹配器
        HashedCredentialsMatcher matcher = new HashedCredentialsMatcher();
        matcher.setHashAlgorithmName("md5");//设置加密算法,加密次数
        matcher.setHashIterations(2);       //设置加密的次数
        matcher.setStoredCredentialsHexEncoded(true);//设置密文16进制,false是base64编码
        return  matcher;
    }

    //返回自定义Realm
    @Bean
    public UserRealm userRealm(){
        UserRealm userRealm = new UserRealm();
        userRealm.setCredentialsMatcher(hashedCredentialsMatcher());//设置密码配置器
        userRealm.setCachingEnabled(false);//取消缓存
        return userRealm;
    }

    //返回安全管理器
    @Bean
    public SecurityManager securityManager(){
//        //创建web项目的安全管理器
//        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//        securityManager.setRealm(userRealm());
//        return securityManager;
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        securityManager.setRealm(userRealm()); //Realm配置
        securityManager.setCacheManager(ehCacheManager());
        //配置自定义会话管理器
        securityManager.setSessionManager(sessionManager());
        return securityManager;
    }




    //返回过滤器对象
    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
        factoryBean.setSecurityManager(securityManager);//配置安全管理器
        factoryBean.setLoginUrl("login.html");//配置登录URL,登录失败进行自动跳转
        //配置授权失败Url
        factoryBean.setUnauthorizedUrl("404.html");
        //配置拦截规则,不拦截在前面,拦截在后面
        //anon不拦截,authc拦截
        Map<String,String> map=new LinkedHashMap<>();
        map.put("/login.html","anon");
        map.put("/register.html" ,"anon");
        map.put("/index.html" ,"anon");
        map.put("/goods.html" ,"anon");
        map.put("/goodsDetails.html" ,"anon");
        map.put("/404.html","anon");
        map.put("/static/**","anon");
        map.put("/user/login/**","anon");
        map.put("/register/login","anon");
        map.put("/type/**" ,"anon");
        map.put("/product/**" ,"anon");
        map.put("/**","authc");//表示所有拦截资源


        factoryBean.setFilterChainDefinitionMap(map);
        return factoryBean;
    }

    //下面的配置用于启动@RequiresRoles 和@ReqriresPermissions 注解
    //基于springaop的实现
    //配置后置处理器
    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor(){
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    @DependsOn({"lifecycleBeanPostProcessor"})
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
        creator.setProxyTargetClass(true);
        return creator;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(){
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager());
        return advisor;

    }

}

注:在ShiroConfig中,添加返回会话管理器对象的方法,在返回安全管理器的方法中,给安全管理器配置会话管理对象 

前后端分离跨域配置

package com.cdz.demo0216yiguo.config;

import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Configuration
public class ShiroCrosConfig extends BasicHttpAuthenticationFilter {

    @Override
    protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin")); //标识允许哪个域到请求,直接修改成请求头的域
        httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");//标识允许的请求方法
        // 响应首部 Access-Control-Allow-Headers 用于 preflight request (预检请求)中,列出了将会在正式请求的 Access-Control-Expose-Headers 字段中出现的首部信息。修改为请求首部
        httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));
        //给option请求直接返回正常状态
        if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
            httpServletResponse.setStatus(HttpStatus.OK.value());
            return false;
        }
        return super.preHandle(request, response);
    }

}

 

不断获得请求头表示已登录(前后端分离,每次请求后台都要传sessionId)

package com.cdz.demo0216yiguo.config;

import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
import org.apache.shiro.web.util.WebUtils;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.util.StringUtils;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import java.io.Serializable;

public class ShiroSessionManager extends DefaultWebSessionManager {

    //这个是请求头中保存sessionid的名称
    private static final String AUTHORIZATION = "authToken";

    private static final String REFERENCED_SESSION_ID_SOURCE = "Stateless request";

    public ShiroSessionManager() {
        super();
    }

    /**
     * 重写返回sessionid的方法
     * @param request
     * @param response
     * @return
     */
    @Override
    protected Serializable getSessionId(ServletRequest request, ServletResponse response) {
        //读取请求头中的sessionid
        String id = WebUtils.toHttp(request).getHeader(AUTHORIZATION);
        System.out.println("id:" + id);
        if (StringUtils.isEmpty(id)) {
            //如果没有携带id参数则按照父类的方式在cookie进行获取
            System.out.println("super:" + super.getSessionId(request, response));
            return super.getSessionId(request, response);
        } else {
            //如果请求头中有 authToken 返回sessionId
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE, REFERENCED_SESSION_ID_SOURCE);
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);
            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
            return id;
        }
    }
}

 注:ShiroSessionManager类继承DefaultWebSessionManager 会话管理器,重写getSessionId方法,获得请求头中的sessionid交给shiro验证

 

后台controller获得已登录id

package com.cdz.demo0216yiguo.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cdz.demo0216yiguo.bean.JsonResult;
import com.cdz.demo0216yiguo.bean.LoginId;
import com.cdz.demo0216yiguo.bean.User;
import com.cdz.demo0216yiguo.service.IUserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.Serializable;
import java.util.List;

@RestController
@RequestMapping("user")
//@CrossOrigin
public class UserControlelr {

    @Autowired
    private IUserService service;

    @ResponseBody
    @GetMapping("user-list")
    public JsonResult listUsers(){
        try{
            List<User> users=service.list();
            return new JsonResult(200,"success",users);
        }catch (Exception e){
            e.printStackTrace();
            return new JsonResult(500,"failed",e.getMessage());
        }
    }
    @GetMapping("/login/username/{username}/pwd/{password}")
    public JsonResult loginY(@PathVariable("username") String userName,@PathVariable("password") String userPwd,String remember, HttpSession session){
        System.out.println("来了没");
        UsernamePasswordToken token = new UsernamePasswordToken();
        token.setUsername(userName);
        token.setPassword(userPwd.toCharArray());
        Subject subject= SecurityUtils.getSubject();
        boolean isNo=true;
        System.out.println(subject.isAuthenticated());
        if(subject.isAuthenticated()==true){
            isNo=false;
        }else{
            isNo=false;
        }
        //判断是否有记住我
//        System.out.println("记住我:"+remember);
//        remember="true";
//        if ("true".equals(remember)) {
//            token.setRememberMe(true);
//        }else{
//            token.setRememberMe(false);
//        }

        if(!isNo){
            try {
                subject.login(token);
                session.setAttribute("username",userName);
                User user_name = service.getOne(new QueryWrapper<User>().eq("user_name", userName));
                System.out.println("用户:"+user_name);
                Serializable id = subject.getSession().getId();
                LoginId ids=new LoginId();
                ids.setUserId(user_name.getUserId());
                ids.setTokenId(id);
                System.out.println("id="+ids);
                return new JsonResult(200,"success",ids);
            }catch (AuthenticationException e){
                e.printStackTrace();
            }
        }
        return new JsonResult(200,"failed","");
    }

    @RequestMapping("add")
    public  JsonResult userAdd(User user,@RequestParam(value="pic" ,required = false) MultipartFile file){
        try{
            User user1=null;
            if(user!=null){
                List<User> users = service.list();
                for(User u:users){
                    if(u.getUserTel().equals(user.getUserTel())){
                        return new JsonResult(200,"failed","");
                    }
                }
                if(file!=null){
                    //获得原来的名
                    String filename = file.getOriginalFilename();
                    //截取后缀名
                    String suffix = filename.substring(filename.lastIndexOf("."));
                    //当前时间创建新名
                    filename=System.currentTimeMillis()+suffix;
                    File upoladFile = new File("G:\\tomcat\\apache-tomcat-8.0.53\\webapps\\upload_images\\" + filename);
                    //保存文件到对象属性中
                    user.setUserImg(filename);
                    //上传文件
                    //上传文件
                    try{
                        file.transferTo(upoladFile);
                    }catch (IOException e){
                        e.printStackTrace();
                    }
                }
                String name=user.getUserName();
                SimpleHash simpleHash6 = new SimpleHash("md5", user.getUserPwd(), ByteSource.Util.bytes(name),2);
                System.out.println("加密6后:"+simpleHash6.toString());
                user.setUserPwd(simpleHash6.toString());
                //System.out.println(user);
                user.setRoleId(57414897);
                service.save(user);
            }
            System.out.println("没有成功");
            return new JsonResult(200,"success",user1);
        }catch (Exception e){
            e.printStackTrace();
            return new JsonResult(500,"failed",e.getMessage());
        }
    }
}

前台请求ID

loadHtml:function(){
	//获得登录后保存的sessionid
	this.token = localStorage.getItem("tokenId");
	//添加到请求头中,请求头名称和Shiro的会话管理器配置的一样
	 axios.defaults.headers.common["authToken"] = this.token;
},

注:客户端登录成功后用localStorage保存sessionid,登录完,再请求后台时,把sessionid取出来,配置到请求头里

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值