1.shiro 是java强大的安全认证框架
- shiro框架的核心功能:认证,授权,会话管理,加密
- shiro框架认证流程
Application Code:应用程序代码,由开发人员负责开发的
Subject:框架提供的接口,代表当前用户对象
SecurityManager:框架提供的接口,代表安全管理器对象
Realm:可以开发人员编写,框架也提供一些,类似于DAO,用于访问权限数据
2.shiro +ssm 登录demo
第一步:引入shiro框架相关的jar
第二步:在web.xml中配置spring框架提供的用于整合shiro框架的过滤器
<!-- shiro filter -->
<filter>
<!-- filter-name必须和配置shiro的过滤工厂bena 的id相同名 -->
<filter-name>shiroFilter</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>shiroFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
第三步:在spring-shiro.xml配置文件中配置bean,id为shiroFilter
<!-- 配置shiro的过滤工厂bena -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/admin/login.jsp"/>
<property name="successUrl" value="/admin/home/home.jsp"/>
<property name="unauthorizedUrl" value="/unauthorized.jsp"/>
<!--指定url拦截策越 -->
<property name="filterChainDefinitions">
<value>
/css/** = anon
/js/** =anon
/images/** = anon
/login.jsp* =anon
/register.jsp* =anon
/login.do* =anon
/register.do* =anon
/checkUser.do* =anon
/* =authc
</value>
</property>
</bean>
第四步:配置安全管理器
<!-- 安全管理器供工厂注入 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> </bean>
第五步:修改UserController中的login方法,使用shiro提供的方式进行认证操作
/*
* 用户登录,使用shiro提供的方式验证
*/
@RequestMapping(value = "/login.do")
public String login(User u, Model model, HttpSession session) {
//获得当前用户到登录对象,现在状态为未认证
Subject subject=SecurityUtils.getSubject();
//用户名密码令牌
AuthenticationToken token=new UsernamePasswordToken(u.getUsername(),Md5Utils.md5(u.getPassword()));
//shiro 使用异常捕捉登录失败消息
try {
//将令牌传到shiro提供的login方法验证,需要自定义realm
subject.login(token);
//没有异常表示验证成功
User user=uservice.login(u);
session.setAttribute("user", user);
return "/home/home";
} catch (IncorrectCredentialsException ice){
model.addAttribute("error","用户名或密码不正确!");
}catch(UnknownAccountException uae){
model.addAttribute("logininfo","未知账户!");
}catch(LockedAccountException lae){
model.addAttribute("logininfo","账户已锁定!");
}catch(ExcessiveAttemptsException eae){
model.addAttribute("logininfo","用户名或密码错误次数太多!");
}catch(AuthenticationException ae){
ae.printStackTrace();
model.addAttribute("logininfo","验证未通过!");
}catch (Exception e) {
model.addAttribute("logininfo","验证未通过!");
}
return "/login";
}
第六步:自定义realm,并注入给安全管理器
public class MyShiroRealm extends AuthorizingRealm {
@Autowired
private UserServiceImpl service;
//授权方法
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
// TODO 未书写权限,只演示登录认证
return null;
}
//认证访法
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("realm------------------------");
UsernamePasswordToken mytoken=(UsernamePasswordToken) token;
String username=mytoken.getUsername();
User u=new User();
u.setUsername(username);
//根据用户名查询数据·库中的密码
User user = service.login(u);
if(user==null) {
//用户不存在
return null;
}
//如果能查询到,再由框架比对数据库中查询到的密码和页面提交的密码是否一致
AuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(),this.getName());
return info;
}
}
注入安全管理器 (自定义realm中注入的service层查数据库,启动项目时会注入失败,需要在注入realm之前,注入service层bean
( <!-- realm 需要先注入service -->
<context:component-scan base-package="com.sj.serviceimpl"/>
)
这的service层和dao层就不再提供了,因为很简单,就是一个根据用户名查询放回用户信息的接口
<!-- 安全管理器供工厂调用 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- 注入自己的realm -->
<property name="realm" ref="myRealms"/>
</bean>
<!--自定义realm -->
<bean id="myRealms" class="com.sj.shiro.MyShiroRealm"/>
完整的shiro配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
">
<!-- realm 需要先注入service -->
<context:component-scan base-package="com.sj.serviceimpl"/>
<!-- 配置shiro的过滤工厂bena -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/admin/login.jsp"/>
<property name="successUrl" value="/admin/home/home.jsp"/>
<property name="unauthorizedUrl" value="/unauthorized.jsp"/>
<!--指定url拦截策越 -->
<property name="filterChainDefinitions">
<value>
/css/** = anon
/js/** =anon
/images/** = anon
/login.jsp* =anon
/register.jsp* =anon
/login.do* =anon
/register.do* =anon
/checkUser.do* =anon
/* =authc
</value>
</property>
</bean>
<!-- 安全管理器供工厂调用 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<!-- 注入自己的realm -->
<property name="realm" ref="myRealms"/>
</bean>
<!--自定义realm -->
<bean id="myRealms" class="com.sj.shiro.MyShiroRealm"/></beans>
shiro配置文件需要引入到spring中,在web.xml原来的spring文件导入中添加 classpath:spring-shiro.xml
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml,
classpath:spring-shiro.xml
</param-value>
</context-param>