SpringBoot整合Shiro

SpringBoot结合Shiro

先了解Shiro是什么

shiro是一个安全框架,可以进行认证、授权、密码加密、会话管理

功能:
Authentication:身份认证/登录,验证用户是不是拥有相应的身份;

Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能做事情,常见的如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限;

Session Manager:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通JavaSE环境的,也可以是如Web环境的;

Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储;

Web Support:Web支持,可以非常容易的集成到Web环境;

Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率;

Concurrency:shiro支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去;

Testing:提供测试支持;

Run As:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问;

对应的pom文件

< dependency>
< groupId>org.apache.shiro</ groupId>
< artifactId>shiro-spring</ artifactId>
< version>1.4.0</ version>
</ dependency>

import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SecurityManager;
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.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
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;
import org.springframework.context.annotation.DependsOn;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroBean {

@Bean
public MyRealm authRealm() {
    MyRealm realm = new MyRealm();
    return realm;
}


@Bean("securityManager")
public DefaultWebSecurityManager getManager(MyRealm realm) {
    DefaultWebSecurityManager manager = new DefaultWebSecurityManager();
    // 使用自己的realm
    manager.setRealm(realm);
    /*
     * 关闭shiro自带的session,详情见文档
     * http://shiro.apache.org/session-management.html#SessionManagement-StatelessApplications%28Sessionless%29
     */
    DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
    DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
    defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
    subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
    manager.setSubjectDAO(subjectDAO);

    return manager;
}

/**
 * Shiro自定义拦截器
 * @param securityManager
 * @return
 */
@Bean
public ShiroFilterFactoryBean shiorFilter(SecurityManager securityManager) {
    ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
    // 必须设置 SecurityManager
    shiroFilterFactoryBean.setSecurityManager(securityManager);
    // 如果不设置默认会自动寻找Web工程根目录下的"/login.jsp"页面
    //shiroFilterFactoryBean.setLoginUrl("/login");
    //配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了
    shiroFilterFactoryBean.setLoginUrl("/login/loadHtml");
    shiroFilterFactoryBean.setUnauthorizedUrl("/login/loadHtml");
    // 拦截器.
    Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
    //配置记住我或认证通过可以访问的地址(配置不会被拦截的链接 顺序判断)
    filterChainDefinitionMap.put("/static/**", "anon");
   filterChainDefinitionMap.put("/js/**", "anon");
    filterChainDefinitionMap.put("/css/**", "anon");
    filterChainDefinitionMap.put("/images/**", "anon");
    filterChainDefinitionMap.put("/face/**", "anon");
    filterChainDefinitionMap.put("/lay/**", "anon");
    filterChainDefinitionMap.put("/modules/**", "anon");
    filterChainDefinitionMap.put("/layui/**", "anon");
    filterChainDefinitionMap.put("/nepadmin/**", "anon");

    //C:\Develop\workspace\cr\paodingsoft\trunk\demo\spring-boot-api-project-seed-master\src\main\resources\static\js\lib\jquery-easyui-1.7.1\jquery.easyui.min.js
    // 配置退出过滤器,其中的具体的退出代码Shiro已经替我们实现了
    filterChainDefinitionMap.put("/login/loginFile", "anon");
    // <!-- 过滤链定义,从上向下顺序执行,一般将 /**放在最为下边 -->:这是一个坑呢,一不小心代码就不好使了;
    // <!-- authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问-->
    filterChainDefinitionMap.put("/**", "authc");

    shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
    return shiroFilterFactoryBean;
}



/**
 * 下面的代码是添加注解支持
 */
@Bean
@DependsOn("lifecycleBeanPostProcessor")
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
    DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
    // 强制使用cglib,防止重复代理和可能引起代理出错的问题
    // https://zhuanlan.zhihu.com/p/29161098
    defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
    return defaultAdvisorAutoProxyCreator;
}

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



/**
 * cookie对象;
 * 记住密码实现起来也是比较简单的,主要看下是如何实现的。
 *
 * @return
 */
@Bean
public SimpleCookie rememberMeCookie() {
    //这个参数是cookie的名称,对应前端的checkbox的name = rememberMe
    SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
    //<!-- 记住我cookie生效时间30天 ,单位秒;-->
    simpleCookie.setMaxAge(259200);
    return simpleCookie;
}

/**
 * cookie管理对象;
 *
 * @return
 */
@Bean
public CookieRememberMeManager rememberMeManager() {
    CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
    cookieRememberMeManager.setCookie(rememberMeCookie());
    return cookieRememberMeManager;
}
@Bean
public SecurityManager securityManagerC() {
    DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
    // 设置realm.
    securityManager.setRealm(authRealm());
    //注入记住我管理器;
    securityManager.setRememberMeManager(rememberMeManager());
    return securityManager;
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {
    AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
    advisor.setSecurityManager(securityManagerC());
    return advisor;
}

}
这里如果是新手应该会出现一个问题:
如果Shiro找不到对应的登录页面的话,会启动它自带的登陆页(shiorFilter这个方法里面配置对应的跳转路径,以给出注解,不懂私信我)
还有一个就是Shiro会重定向你的地址,如果在未登录的情况下(你下面所有的路径都会报302错误,将你所有的静态资源全部放过去,shiorFilter这个方法里面配置对应的跳转路径,以给出注解,不懂私信我)
下一步配置功能代码
import com.company.project.dao.TbSysUserMapper;
import com.company.project.model.TbSysUser;
import com.company.project.service.TbSysDeptService;
import com.company.project.service.TbSysUserService;
import com.company.project.util.JWTUtil;
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 javax.annotation.Resource;

public class MyRealm extends AuthorizingRealm {

@Autowired
private TbSysUserService  server;


@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
    String username = JWTUtil.getUsername(principals.toString());
    System.out.println(username);
    SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
    simpleAuthorizationInfo.addStringPermission("1212312");
    return simpleAuthorizationInfo;
}

@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
    String  name =(String) token.getPrincipal();
    TbSysUser  user=server.findBy("userName",name);
    System.out.println(user.getPassword());
    if(user!=null){
        AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(name, user.getPassword(),"xxx");
        return authcInfo;
    }else{
        return null;
    }


}

}
记住这两个方法一定要有返回值,如果没有返回值会导致接口Controller报错
如果返回空值可以利用作为空值判断,然后在Controller做try-catch处理
Controller接口类
@RequestMapping("/loginFile")
@ResponseBody
public String getIsOkToTemp(@RequestParam(name=“name”,required=false)String name,@RequestParam(name=“pwd”,required=false) String pwd, @RequestParam(name=“autoLogin”,required=false,defaultValue=“No”) String autoLogin){
UsernamePasswordToken token = new UsernamePasswordToken(name, MD5Util.encrypt(pwd));
Subject subject = SecurityUtils.getSubject();
try {
subject.login(token);
String userName = (String) subject.getPrincipal();
TbSysUser currentUser =null;
return “tableHtml”;
} catch (Exception e) {
System.out.println(1111);
e.printStackTrace();
return “{error:404,message:‘The Account Is Not Exist Or The Password Is Error’}”;
}

}
如果不做处理返回null  Subject subject = SecurityUtils.getSubject();这个方法会报错

Shiro配置就完成了,记住登录操作它会自动记录
不然你访问的任何项目连接都会重定向到你所配置的登录页
不懂私信我,滴滴我

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值