SSM集成Shiro安全框架(三)

本文档介绍了如何在SSM(Spring、SpringMVC、MyBatis)项目中集成Shiro安全框架,实现了角色OR关系的过滤,并详细讲述了Shiro与kaptcha验证码的整合步骤,包括配置文件、过滤器、认证令牌、登录页面以及控制器的修改。此外,还提供了完整的demo源码供下载参考。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

七、实现or关系的角色过滤

1.RoleOrFilterAuthorizationFilter.java

package com.yan.shiro.common;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authz.AuthorizationFilter;

public class RoleOrFilterAuthorizationFilter extends AuthorizationFilter{

	@Override
	protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
		Subject subject = getSubject(request, response);  
        String[] rolesArray = (String[]) mappedValue;  

        if (rolesArray == null || rolesArray.length == 0) 
        {  
            return true;  
        }  
        for(int i=0;i<rolesArray.length;i++)
        {
            if(subject.hasRole(rolesArray[i]))
            {  
                return true;  
            }  
        }  
        return false;
	}

}

2.applicationContext-shiro.xml

	<bean id="shiroFilter"
		class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
		<!-- 调用我们配置的权限管理器 -->
		<property name="securityManager" ref="securityManager" />
		<!-- 配置我们的登录请求地址 -->
		<property name="loginUrl" value="/login.jsp" />
		<!-- 配置我们在登录页登录成功后的跳转地址,如果你访问的是非/login地址,则跳到您访问的地址  -->
		<property name="successUrl" value="/index.jsp" />
		<!-- 如果您请求的资源不再您的权限范围,则跳转到/403请求地址 -->
		<property name="unauthorizedUrl" value="/unauthorized.jsp" />
		<property name="filters">
			<util:map>
				<!-- 自定义roleOrFilter -->
				<entry key="roleOrFilter" value-ref="roleOrFilter" />
				<entry key="logout" value-ref="logoutFilter" />
			</util:map>
		</property>
/index.jsp = roleOrFilter["admin","productManager"] <!--只需具有其中一个权限就可以,但需要自定义filter -->
<!--自定义的filter -->
	<bean id="roleOrFilter" class="com.yan.shiro.common.RoleOrFilterAuthorizationFilter"></bean>

八、shiro集成kaptcha验证码

1.pom.xml

		<!-- Shiro 集成验证码 -->
		<dependency>
			<groupId>com.github.penggle</groupId>
			<artifactId>kaptcha</artifactId>
			<version>2.3.2</version>
		</dependency>

2.spring-mvc.xml配置文件

    <!-- 配置kaptcha验证码 -->  
    <bean id="captchaProducer" class="com.google.code.kaptcha.impl.DefaultKaptcha">  
        <property name="config">  
            <bean class="com.google.code.kaptcha.util.Config">  
                <constructor-arg type="java.util.Properties">  
                    <props>  
                        <prop key="kaptcha.image.width">100</prop>  
                        <prop key="kaptcha.image.height">50</prop>  
                        <prop key="kaptcha.noise.impl">com.google.code.kaptcha.impl.NoNoise</prop>  
                        <prop key="kaptcha.textproducer.char.string">0123456789abcdefghijklmnopqrstuvwxyz</prop>  
                        <prop key="kaptcha.textproducer.char.length">4</prop>  
                    </props>  
                </constructor-arg>  
            </bean>  
        </property>  
    </bean> 

3.applicationContext-shiro.xml

<!-- 配置我们的登录请求地址 -->
		<property name="loginUrl" value="/login.jsp" />
!-- 将自定义 的FormAuthenticationFilter注入shiroFilter中-->
				<entry key="authc" value-ref="myAuthenFilter" /> 
/login.jsp=authc
<bean id="myAuthenFilter" class="com.yan.shiro.common.CaptchaFormAuthenticationFilter"/>

4.CaptchaFormAuthenticationFilter.java

package com.yan.shiro.common;

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

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.yan.shiro.exception.IncorrectCaptchaException;

public class CaptchaFormAuthenticationFilter extends FormAuthenticationFilter {
	private static final Logger LOG = LoggerFactory.getLogger(CaptchaFormAuthenticationFilter.class);

	private static void sysout() {
		System.out.println("CaptchaFormAuthenticationFilter");
	}

	public CaptchaFormAuthenticationFilter() {
	}

	@Override
	/**
	 * 登录验证
	 */
	protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
		System.out.println("executeLogin");
		CaptchaUsernamePasswordToken token = createToken(request, response);
		try {
			/* 图形验证码验证 */
			doCaptchaValidate((HttpServletRequest) request, token);
			Subject subject = getSubject(request, response);
			subject.login(token);// 正常验证
			LOG.info(token.getUsername() + "登录成功");
			return onLoginSuccess(token, subject, request, response);
		} catch (AuthenticationException e) {
			LOG.info(token.getUsername() + "登录失败--" + e);
			return onLoginFailure(token, e, request, response);
		}
	}

	// 验证码校验
	protected void doCaptchaValidate(HttpServletRequest request, CaptchaUsernamePasswordToken token) {
		System.out.println("doCaptchaValidate");
		// session中的图形码字符串
		String captcha = (String) request.getSession().getAttribute(com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
		// 比对
		if (captcha != null && !captcha.equalsIgnoreCase(token.getCaptcha())) {
			throw new IncorrectCaptchaException("验证码错误!");
		}
	}

	@Override
	protected CaptchaUsernamePasswordToken createToken(ServletRequest request, ServletResponse response) {
		String username = getUsername(request);
		String password = getPassword(request);
		String captcha = getCaptcha(request);
		boolean rememberMe = isRememberMe(request);
		String host = getHost(request);
		return new CaptchaUsernamePasswordToken(username, password.toCharArray(), rememberMe, host, captcha);
	}

	public static final String DEFAULT_CAPTCHA_PARAM = "captcha";

	private String captchaParam = DEFAULT_CAPTCHA_PARAM;

	public String getCaptchaParam() {
		return captchaParam;
	}

	public void setCaptchaParam(String captchaParam) {
		this.captchaParam = captchaParam;
	}

	protected String getCaptcha(ServletRequest request) {
		return WebUtils.getCleanParam(request, getCaptchaParam());
	}

	// 保存异常对象到request
	@Override
	protected void setFailureAttribute(ServletRequest request, AuthenticationException ae) {
		request.setAttribute(getFailureKeyAttribute(), ae);
	}
}

5.CaptchaUsernamePasswordToken.java

package com.yan.shiro.common;

import org.apache.shiro.authc.UsernamePasswordToken;

public class CaptchaUsernamePasswordToken extends UsernamePasswordToken{
	//验证码字符串
	private String captcha;
 
	public CaptchaUsernamePasswordToken(String username, char[] password,
			boolean rememberMe, String host, String captcha) {
		super(username, password, rememberMe, host);
		this.captcha = captcha;
	}
 
	public String getCaptcha() {
		return captcha;
	}
 
	public void setCaptcha(String captcha) {
		this.captcha = captcha;
	}
}

6.login.jsp

<%@page import="org.apache.shiro.web.filter.authc.FormAuthenticationFilter"%>
<%@page import="com.yan.shiro.exception.IncorrectCaptchaException"%>
<%@page import="org.apache.shiro.authc.AuthenticationException"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%
	String path = request.getContextPath();
	String basePath = request.getScheme() + "://"
			+ request.getServerName() + ":" + request.getServerPort()
			+ path + "/";
%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<base href="<%=basePath%>">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<style type="text/css">
.error {
	color: red;
}
</style>
<script type="text/javascript">
function refreshCaptcha(){
	document.getElementById("img_captcha").src="http://localhost:8081/ShiroDemo/kaptcha?t=" + Math.random();
}
</script>
</head>
<body>
 
	<%
		Object obj = request
				.getAttribute(FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME);
		String msg = "";
		if (obj != null) {
			if (obj instanceof IncorrectCaptchaException)
				msg = "验证码错误!";
			else 
				msg = "账号或密码错误!";
		}
		
		out.println("<div class='error'>" + msg + "</div>");
	%>
 
	<form action="login.jsp" method="post">
		<input type="hidden" name="rememberMe" value="0" /> <br />
		<table>
 
			<tr>
				<td>用户帐号:</td>
				<td><input type="text" name="username" id="username" value="" /></td>
			</tr>
			<tr>
				<td>登录密码:</td>
				<td><input type="password" name="password" id="password"
					value="" /></td>
			</tr>
			<tr>
				<td>验证码:</td>
				<td><input type="text" name="captcha" /></td>
			</tr>
			<tr>
				<td> </td>
				<td><img alt="验证码" src="http://localhost:8081/ShiroDemo/kaptcha" title="点击更换"
					id="img_captcha" onclick="javascript:refreshCaptcha();">(看不清<a href="javascript:void(0)" onclick="javascript:refreshCaptcha()">换一张</a>)</td>
			</tr>
			<tr>
				<td colspan="2"><input value="登录" type="submit"></td>
			</tr>
		</table>
 
	</form>
</body>
</html>

7.Controller.java

    @Autowired
    private Producer captchaProducer;

    @RequestMapping(value = "/kaptcha")
    public void getKaptchaImage(HttpServletRequest request, HttpServletResponse response) throws Exception {
        HttpSession session = request.getSession();
        response.setDateHeader("Expires", 0);
        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
        response.addHeader("Cache-Control", "post-check=0, pre-check=0");
        response.setHeader("Pragma", "no-cache");
        response.setContentType("image/jpeg");
        //生成验证码
        String capText = captchaProducer.createText();
        session.setAttribute(Constants.KAPTCHA_SESSION_KEY, capText);
        //向客户端写出
        BufferedImage bi = captchaProducer.createImage(capText);
        ServletOutputStream out = response.getOutputStream();
        ImageIO.write(bi, "jpg", out);
        try {
            out.flush();
        } finally {
            out.close();
        }
    }
     /**
     * 获取验证码
     * 
     * @author atd681
     * @since 2018年8月13日
     */
	@RequestMapping("/kaptcha/get")
    @ResponseBody
    public String getKaptcha(HttpSession session) {
        // Kaptcha生成验证后保存SESSION中的KEY为KAPTCHA_SESSION_KEY
        return (String) session.getAttribute("KAPTCHA_SESSION_KEY");
    }

九、demo下载

GitHub:https://github.com/709248556/shiroDemo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值