之前写了一个自己的系统框架,一直在闲暇的时候向里面添加的一些功能,最近整合了shiro框架。(稍微吐槽下,它说自己使用简单,额就他们的API像我这种菜鸟真的是无力吐槽,最后还是参考了一些博文在加上不断的尝试才算有点小头绪)。
废话就不多说了,shiro的介绍我也不多说了(自己也不是很了解,官网上的介绍的四大核心功能现在就尝试了,一个身份验证),官网上有很详细的介绍。
依赖包:
<!-- shrio start -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-aspectj</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.3.2</version>
</dependency>
web.xml
<!-- The filter-name matches name of a 'shiroFilter' bean inside applicationContext.xml -->
<filter>
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
<init-param>
<param-name>targetFilterLifecycle</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<!-- Make sure any request you want accessible to Shiro is filtered. /*
catches all -->
<!-- requests. Usually this filter mapping is defined first (before all
others) to -->
<!-- ensure that Shiro works in subsequent filters in the filter chain: -->
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
applicationContext.xml
<!-- 6.shiro -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/jump/index"/>
<property name="successUrl" value="/jump/home"/>
<property name="unauthorizedUrl" value="/unauthorized"/>
<!-- The 'filters' property is usually not necessary unless performing an override, which we
want to do here (make authc point to a PassthruAuthenticationFilter instead of the
default FormAuthenticationFilter: -->
<!-- <property name="filters">
<util:map>
<entry key="authc">
<bean class="org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter"/>
</entry>
</util:map>
</property> -->
<property name="filterChainDefinitions">
<value>
<!-- /signup = anon -->
/jump/index=anon
/user/login=anon
/common/getVerificationCode=anon
/error/**=anon
/static/**=anon
/**= authc
</value>
</property>
</bean>
<!-- <bean id="someFilter" class="..." /> -->
<!-- <bean id="anotherFilter" class="..."> </bean> -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="MyRealm" />
<!-- <property name="sessionMode" value="native"/> -->
</bean>
<!-- <bean id="myRealm" class="util.shiro.MyRealm">
</bean> -->
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<!-- 启动shiro注释 -->
<bean
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
depends-on="lifecycleBeanPostProcessor" />
<bean
class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>
MyRealm.java 领域处理
package util.shiro;
import javax.annotation.Resource;
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.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.stereotype.Component;
import dao.user.UserManageDao;
import entities.login.User;
@Component("MyRealm") //这里是使用注解注册bean 也可以在application.xml <bean id="myRealm" class="util.shiro.MyRealm"> 直接注册
public class MyRealm extends AuthorizingRealm {
@Resource
private UserManageDao userManageDao;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
return null;
}
/**
* 登录认证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken arg0) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken)arg0;
String name=token.getUsername();
User user=userManageDao.getUser(name);
if(user!=null){
return new SimpleAuthenticationInfo(user.getName(),user.getPassword(),getName());
}else{
throw new AuthenticationException();
}
}
}
然后是登录controller
package controller.login;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import service.login.LoginService;
@Controller
@RequestMapping("/user")
public class LoginController{
@Resource
private LoginService loginService;
@RequestMapping(value="/login",method=RequestMethod.POST)
public String login(
RedirectAttributes redirectAttributes,
String name,
String password,
String code,
Model model,
HttpServletRequest req){
try{
UsernamePasswordToken token = new UsernamePasswordToken(name,password);
Subject currentUser = SecurityUtils.getSubject();
//if (!currentUser.isAuthenticated()){
//使用shiro来验证
//token.setRememberMe(true);
currentUser.login(token);//验证角色和权限
//通过debug可以知道当运行currentUser.login(token)这个会进入myRealm的方法里面
// }
String verificationCode= req.getSession().getAttribute("verificationCode").toString();
req.getSession().setAttribute("isLogin",true);
if(verificationCode.equals(code)){
return "home";
}
if(!verificationCode.equals(code)){
model.addAttribute("message", "验证码错误");
return "index";
}
}catch(Exception e){
e.printStackTrace();
model.addAttribute("message", "用户名或密码错误");
}
return "index";
}
}
<property name="loginUrl" value="/jump/index"/> 跳转的页面
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" errorPage="error/500.jsp"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath}/static/plugin/easyui/themes/gray/easyui.css">
<link type="text/css" rel="stylesheet" href="${pageContext.request.contextPath}/static/plugin/easyui/themes/icon.css">
<script type="text/javascript" src="${pageContext.request.contextPath}/static/plugin/easyui/jquery.min.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/static/plugin/easyui/jquery.easyui.min.js"></script>
<c:set var="ctx" value="${pageContext.request.contextPath}"/>
<title>登陆页面</title>
<script type="text/javascript">
$(function(){
if(!'${message}'==''){
$.messager.alert('提示','${message}');
}
})
//刷新验证码
function refreshVerificationCode(){
$("#verificationCodeImg").attr("src","${ctx}/common/getVerificationCode?date=" + new Date());
}
</script>
<script type="text/javascript" src="${ctx}/static/js/index.js"></script>
</head>
<body style="background-image:url('${ctx}/static/img/login1.jpg')">
<div align="center" style="margin-top:10%">
<form id="loginForm" action="${ctx}/user/login" method="POST">
<table style="color:#fff;box-shadow: 0px 0px 20px #000;border-spacing:20px;width:50%;font-family:'Microsoft YaHei';background:#74757d">
<tr>
<td ><span style="font-size:2em;text-align:left">测试专用系统</span></td>
</tr>
<tr>
<td style="text-align:center"><input class="easyui-textbox" id="name" type="text" name="name" value="用户名" style="height:25px;width:200px" ></input></td>
</tr>
<tr>
<td style="text-align:center"><input class="easyui-textbox" id="password" type="password" name="password" value="密码" style="height:25px;width:200px"></input></td>
</tr>
<tr>
<td style="text-align:center">
<input class="easyui-textbox" id="code" type="text" name="code" value="验证码" style="height:25px;width:200px"></input>
</td>
</tr>
<tr>
<td style="text-align:right">
<img id="verificationCodeImg" alt="..." src="${ctx}/common/getVerificationCode">
<a href="#" class="easyui-linkbutton" onclick="refreshVerificationCode()" style="height:25px;width:150px">看不清?</a></td>
</tr>
<tr>
<td style="text-align:right">
<a href="#" class="easyui-linkbutton" onclick="loginSumbit()" style="height:25px;width:200px;background-color:blue">GO</a></td>
</tr>
</table>
</form>
</div>
</body>
</html>
一定要注意 下面的配置
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/jump/index"/>
<property name="successUrl" value="/jump/home"/>
<property name="unauthorizedUrl" value="/unauthorized"/>
<!-- The 'filters' property is usually not necessary unless performing an override, which we
want to do here (make authc point to a PassthruAuthenticationFilter instead of the
default FormAuthenticationFilter: -->
<!-- <property name="filters">
<util:map>
<entry key="authc">
<bean class="org.apache.shiro.web.filter.authc.PassThruAuthenticationFilter"/>
</entry>
</util:map>
</property> -->
<property name="filterChainDefinitions">
<value>
<!-- anon:是不需要身份验证就可以访问,authc:需要身份验证
一定要注意这个配置
从上面的介绍可以知道
/jump/index 是跳转到登录页
/user/login 是登录提交的controller
/common/getVerificationCode 是获得验证码
/error/**=anon
/static/**=anon 这两个是静态资源
这些都是在登录之前需要访问的资源 也就是说你没登录之前也要能正常访问不然就会报错
如果我没有设置 /static/**=anon 这个就会出现 我上面的登录页JQ无法使用 引用的JS无效
/common/getVerificationCode=anon 没设置我的验证码图片就加载不了。
通过这个可以知道每当你访问一个URL不管是controller还是静态引用都需要通过身份验证当然设置为anon的除外
-->
/jump/index=anon
/user/login=anon
/common/getVerificationCode=anon
/error/**=anon
/static/**=anon
/**= authc
</value>
</property>
</bean>