1.首先,导入shiro的依赖
<!-- shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-ehcache</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-quartz</artifactId>
<version>${shiro.version}</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>${shiro.version}</version>
</dependency>
其中${shiro.version}是<shiro.version>1.3.2</shiro.version>
2.在web.xml里配置shiro的过滤器
<!--配置Shiro的过滤器-->
<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>
<!--以下配置要过滤的url,即用到shiro功能的url-->
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/tologin</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/login</url-pattern>
</filter-mapping>
注意:要把classpath:spring-mybatis.xml改成classpath:spring-*.xml,以加载所有与spring相关的配置文件。
3.添加配置文件spring-shiro.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!-- Shiro的Web过滤器 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<!-- Shiro的安全管理器,所有关于安全的操作都会经过SecurityManager -->
<property name="securityManager" ref="securityManager"/>
<!-- 系统认证提交地址,如果用户退出即session丢失就会访问这个页面 -->
<property name="loginUrl" value="/tologin"/>
<!-- 权限验证失败跳转的页面,需要配合Spring的ExceptionHandler异常处理机制使用 -->
<property name="unauthorizedUrl" value="/unauthorized.jsp"/>
<property name="filters">
<util:map>
<entry key="authc" value-ref="formAuthenticationFilter"/>
</util:map>
</property>
<!-- 自定义的过滤器链,从上向下执行,一般将`/**`放到最下面 -->
<property name="filterChainDefinitions">
<value>
<!-- 静态资源不拦截 -->
/css/** = anon
/image/** = anon
/js/** = anon
<!-- 登录页面不拦截 -->
/login = anon
/tologin = anon
<!-- Shiro提供了退出登录的配置`logout`,会生成路径为`/logout`的请求地址,访问这个地址即会退出当前账户并清空缓存 -->
/logout = logout
<!-- user表示身份通过或通过记住我通过的用户都能访问系统 -->
/home = user
<!-- `/**`表示所有请求,表示访问该地址的用户是身份验证通过或RememberMe登录的都可以 -->
/** = user
</value>
</property>
</bean>
<!-- 基于Form表单的身份验证过滤器 -->
<bean id="formAuthenticationFilter" class="org.apache.shiro.web.filter.authc.FormAuthenticationFilter">
<property name="usernameParam" value="username"/>
<property name="passwordParam" value="password"/>
<property name="loginUrl" value="/login.jsp"/>
</bean>
<!-- 安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="userRealm"/>
</bean>
<!-- Realm实现 -->
<bean id="userRealm" class="com.lzw.emall.realm.UserRealm"></bean>
</beans>
4.UserRealm的代码实现
package com.lzw.emall.realm;
import com.lzw.emall.bean.User;
import com.lzw.emall.service.UserService;
import org.apache.shiro.authc.*;
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;
public class UserRealm extends AuthorizingRealm {
@Autowired
private UserService userService;
/**
* 权限校验
*/
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
return authorizationInfo;
}
/**
* 身份校验
*/
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
String username = (String) token.getPrincipal();
User user = userService.findByName(username);
if (user == null) {
throw new UnknownAccountException(); //没有找到账号
}
//交给AuthenticationRealm使用CredentialsMatcher进行密码匹配
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
user.getUsername(), //用户名
user.getPassword(), //密码
getName() //realm name
);
return authenticationInfo;
}
}
5.LoginController的实现
//登陆
@RequestMapping("/login")
public String login(HttpServletRequest request, Model model) {
String username = request.getParameter("username");
String password = request.getParameter("password");
User user = userService.findByName(username);
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
try {
subject.login(token);
Session session = subject.getSession();
session.setAttribute("subject", subject);
/* request.getSession().setAttribute("username",user.getUsername());
request.getSession().setAttribute("userid",user.getUserId());
request.getSession().setAttribute("address",user.getAddress());
request.getSession().setAttribute("realname",user.getRealname());
request.getSession().setAttribute("telephone",user.getTelephone());
request.getSession().setAttribute("sex",user.getSex());
if(request.getSession().getAttribute("carts")!=null)
orderService.sessionToCart(request);*/
return "home";
} catch (AuthenticationException e) {
return "redirect:/tologin?state=error";
}
}