软件编程
位置:首页>> 软件编程>> java编程>> springboot整合shiro与自定义过滤器的全过程

springboot整合shiro与自定义过滤器的全过程

作者:yx726843014  发布时间:2023-11-24 21:02:40 

标签:springboot,shiro,整合

filter自定义过滤器  增加了 对验证码的校验

package com.youxiong.filter;

import com.youxiong.shiro.UsernamePasswordKaptchaToken;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;

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

public class FormValid extends FormAuthenticationFilter {

private String kaptcha = "KAPTCHA_SESSION_KEY";

public FormValid() {
       super();
   }

//用户未登录
/*   @Override
   protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
       HttpServletRequest httpServletRequest = (HttpServletRequest) request;
       HttpSession session = httpServletRequest.getSession();
       String kaptchaCode = (String) session.getAttribute(kaptcha);
       String code = httpServletRequest.getParameter("code");
       if(code!=null&&kaptchaCode!=null&&!kaptchaCode.equals(code)){
           httpServletRequest.setAttribute("shiroLoginFailure","codeError");
           return true;
       }
       return super.onAccessDenied(request, response);
   }
*/
   //用户提交表单时候  创建的token
   @Override
   protected AuthenticationToken createToken( ServletRequest request, ServletResponse response) {
       HttpServletRequest httpServletRequest = (HttpServletRequest) request;
       String code = (String) httpServletRequest.getParameter("kaptcha");
       String host = getHost(request);
       String username = getUsername(request);
       String password = getPassword(request);
       boolean rememberMe = isRememberMe(request);
       System.out.println("create token--------------code------>one "+code);
       return new UsernamePasswordKaptchaToken(username,password.toCharArray(),rememberMe,host,code);
   }
}

自定义UsernamePassword是为了接收前台发送过来的数据

package com.youxiong.shiro;

import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;

import java.io.Serializable;

public class UsernamePasswordKaptchaToken extends UsernamePasswordToken {

private static final long serialVersionUID = 1L;

private String kaptcha;

public UsernamePasswordKaptchaToken(){
       super();
   }

public UsernamePasswordKaptchaToken(String username, char[] password, boolean rememberMe, String host, String kaptcha) {
       super(username, password, rememberMe, host);
       this.kaptcha = kaptcha;
   }

public String getKaptcha() {
       return kaptcha;
   }

public void setKaptcha(String kaptcha) {
       this.kaptcha = kaptcha;
   }
}

shiro配置

package com.youxiong.config;

import com.google.code.kaptcha.servlet.KaptchaServlet;
import com.youxiong.dao.UserReposisty;
import com.youxiong.domain.Permission;
import com.youxiong.domain.Role;
import com.youxiong.domain.UserInfo;
import com.youxiong.filter.FormValid;
import com.youxiong.redis.JedisCacheManager;
import com.youxiong.redis.RedisSessionDao;
import com.youxiong.redis.RedisSessionListener;
import com.youxiong.redis.RediseSessionFactory;
import com.youxiong.shiro.MyShiroRealm;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.SessionListener;
import org.apache.shiro.session.mgt.SessionFactory;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.session.mgt.eis.EnterpriseCacheSessionDAO;
import org.apache.shiro.session.mgt.eis.SessionDAO;
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.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.handler.SimpleMappingExceptionResolver;

import javax.servlet.Filter;
import java.util.*;

@Configuration
public class ShiroConfig {

@Autowired
   private UserReposisty userReposisty;

@Bean
   public ShiroFilterFactoryBean createShiroFilter(SecurityManager securityManager) {
       System.out.println("--------ShiroFilterFactoryBean-------");
       ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
       shiroFilterFactoryBean.setSecurityManager(securityManager);
       Map<String, Filter> filterMap = new HashMap<>();
       //map里面key值要为authc才能使用自定义的过滤器
       filterMap.put("authc", formValid());

// can go to login
       shiroFilterFactoryBean.setLoginUrl("/login.html");
       //doLogin success go to page
       shiroFilterFactoryBean.setSuccessUrl("/success.html");
       //do not Unauthorized page
       shiroFilterFactoryBean.setUnauthorizedUrl("/403.html");
       Map<String, String> map = new LinkedHashMap<String, String>();
       //验证码的路径   不要跟下面需要认证的写在一个路径里  会被拦截的
       map.put("/servlet/**", "anon");
       //需要把要授权的URL  全部装到filterChain中去过滤
       UserInfo userInfo = userReposisty.findByUid(1);
       for (Role role : userInfo.getRoles()) {
           for (Permission permission : role.getPermissions()) {
               if (permission.getUrl() != "") {
                   String permissions = "perms[" + permission.getPermission() + "]";
                   map.put(permission.getUrl(), permissions);
               }
           }
       }
       map.put("/user*/*", "authc");
       shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
       shiroFilterFactoryBean.setFilters(filterMap);

return shiroFilterFactoryBean;
   }

//自己定义realm
   @Bean
   public MyShiroRealm myShiroRealm() {
       MyShiroRealm myShiroRealm = new MyShiroRealm();
       return myShiroRealm;
   }

@Bean
   public SecurityManager securityManager() {
       DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
       securityManager.setRealm(myShiroRealm());
       //缓存管理
       securityManager.setCacheManager(jedisCacheManager());
       //会话管理
       securityManager.setSessionManager(sessionManager());
       return securityManager;
   }

//密码盐   可以不必实现    因为一般密码可以自己定义自己的密码加密规则
/*    @Bean
   public HashedCredentialsMatcher hashedCredentialsMatcher(){
       HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
       hashedCredentialsMatcher.setHashAlgorithmName("md5");
       hashedCredentialsMatcher.setHashIterations(2);
       return hashedCredentialsMatcher;
   }*/

//开启aop注解
   @Bean
   public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
       AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
       authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
       return authorizationAttributeSourceAdvisor;
   }

@Bean(name = "simpleMappingExceptionResolver")
   public SimpleMappingExceptionResolver
   createSimpleMappingExceptionResolver() {
       SimpleMappingExceptionResolver r = new SimpleMappingExceptionResolver();
       Properties mappings = new Properties();
       mappings.setProperty("DatabaseException", "databaseError");//数据库异常处理
       mappings.setProperty("UnauthorizedException", "403");
       r.setExceptionMappings(mappings);  // None by default
       r.setDefaultErrorView("error");    // No default
       r.setExceptionAttribute("ex");     // Default is "exception"
       //r.setWarnLogCategory("example.MvcLogger");     // No default
       return r;
   }

//servlet注册器   -----》验证码的路径
   @Bean
   public ServletRegistrationBean servletRegistrationBean() {
       System.out.println("----验证码---");
       return new ServletRegistrationBean(new KaptchaServlet(), "/servlet/kaptcha.jpg");
   }

//自定义过滤器 ---》里面实现了对验证码校验
   @Bean("myFilter")
   public FormValid formValid() {
       return new FormValid();
   }

//jedis缓存
   @Bean
   public JedisCacheManager jedisCacheManager() {
       return new JedisCacheManager();
   }

@Bean
   public SessionManager sessionManager() {
       DefaultWebSessionManager defaultWebSessionManager = new DefaultWebSessionManager();
       defaultWebSessionManager.setSessionIdCookie(simpleCookie());
       defaultWebSessionManager.setSessionDAO(sessionDAO());
       //可以设置shiro提供的会话管理机制
       //defaultWebSessionManager.setSessionDAO(new EnterpriseCacheSessionDAO());
       return defaultWebSessionManager;
   }

//这里就是会话管理的操作类
   @Bean
   public SessionDAO sessionDAO() {
       return new RedisSessionDao();
   }

//这里需要设置一个cookie的名称  原因就是会跟原来的session的id值重复的
   @Bean
   public SimpleCookie simpleCookie() {
       SimpleCookie simpleCookie = new SimpleCookie("REDISSESSION");
       return simpleCookie;
   }
}

Shiro中的权限控制

#需要同时拥有order:add和order:query权限才可以访问
/order-add = perms["order:add","order:query"]
#只需要order:del权限就可以访问
/order-del = perms["order:del"]

perms表示的就是权限控制,中括号中就是需要访问等号之前路径,需要的权限名称。如果在使用Shiro过滤器的时候,不配置过滤器,就会使用默认的过滤器。

以下是默认权限过滤器的源码。

public class PermissionsAuthorizationFilter extends AuthorizationFilter {
    public PermissionsAuthorizationFilter() {
    }

    public boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws IOException {
        Subject subject = this.getSubject(request, response);
        String[] perms = (String[])mappedValue;
        boolean isPermitted = true;
        if (perms != null && perms.length > 0) {
            if (perms.length == 1) {
                if (!subject.isPermitted(perms[0])) {
                    isPermitted = false;
                }
            } else if (!subject.isPermittedAll(perms)) {
                isPermitted = false;
            }
        }

        return isPermitted;
    }
}

从上面的代码可以看出,我们的配置会默认被强转为string类型的字符串数组。当只有一个权限时,会直接判断有没有该权限; 当配置多个权限时,从下面的代码可以看出只用在请求url的用户拥有所有的权限时,才会返回true,否则就会被拒绝访问。

来源:https://blog.csdn.net/xieliaowa9231/article/details/78996451

0
投稿

猜你喜欢

手机版 软件编程 asp之家 www.aspxhome.com