springboot整合shiro与自定义过滤器的全过程
作者:yx726843014 时间:2023-11-24 21:02:40
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
标签:springboot,shiro,整合
0
投稿
猜你喜欢
SpringBoot 如何实现异步编程
2023-04-15 13:45:43
Java8新特性:函数式编程
2021-12-01 03:09:02
Java使用数组实现ArrayList的动态扩容的方法
2023-03-23 11:24:39
Java 多线程同步 锁机制与synchronized深入解析
2023-12-20 17:55:50
关于javascript冒泡与默认事件的使用详解
2023-05-16 07:16:32
Android zygote启动流程详解
2023-09-13 07:44:12
使用C#实现在屏幕上画图效果的代码实例
2022-09-11 05:12:32
Linux下用java -jar运行可执行jar包的方法教程
2022-11-24 18:01:46
Java 反射调用静态方法的简单实例
2021-10-09 06:47:58
Android使用WindowManager构造悬浮view
2022-08-03 00:43:13
java连接SQL Server数据库的超详细教程
2023-04-05 21:46:22
使用BindingResult 自定义错误信息
2023-09-02 17:43:01
android通过servlet上传文件到服务器
2021-10-07 05:44:02
全面了解java基本类型和封装类型的区别及应用
2022-10-03 05:39:09
用C#缩小照片上传到各种空间的具体方法
2022-03-28 02:29:18
JAVA图片水印开发案例详解
2023-06-20 02:06:53
java通过方向键控制小球移动的小游戏
2023-11-10 05:25:59
Android中Activity的四种启动模式和onNewIntent()
2022-09-05 23:15:02
java编程实现优先队列的二叉堆代码分享
2022-11-13 15:32:13
springboot读取resources下文件的方式详解
2022-05-21 16:14:48