- Spring配置securityManager//程序里面就不用SecurityUtils.setSecurityManager(securityManager); // 注入SecurityManager
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="cacheManager" ref="cacheManager"/>
<property name="realms" ref="jdbcRealm"/>
</bean>
- 配置缓存CacheManager
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManagerConfigFile" value="classpath:ehcache.xml"/>
</bean>
<bean id="authenticator" class="org.apache.shiro.authc.pam.ModularRealmAuthenticator">
<property name="authenticationStrategy">
<bean class="org.apache.shiro.authc.pam.AtLeastOneSuccessfulStrategy"></bean>
</property>
</bean>
- 配置 Realm 就是自定义的realm
- `
这里的realm只需要实现AuthorizingRealm接口就行,因为里面包含两个需要重写的方法doGetAuthenticationInfo–进行登录授权,doGetAuthorizationInfo进行角色授权。
4.配置 LifecycleBeanPostProcessor
<bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
<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>
5.启用 IOC 容器中使用 shiro 的注解. 但必须在配置了 LifecycleBeanPostProcessor 之后才可以使用
配置 ShiroFilter.
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="/login.jsp"/>
<property name="successUrl" value="/list.jsp"/>
<property name="unauthorizedUrl" value="/unauthorized.jsp"/>
<!--
配置哪些页面需要受保护.
以及访问这些页面需要的权限.
1). anon 可以被匿名访问
2). authc 必须认证(即登录)后才可能访问的页面.
3). logout 登出.
4). roles 角色过滤器
-->
<property name="filterChainDefinitions">
<value>
/login.jsp = anon
/shiro/login=anon
/shiro/logout=logout
/user.jsp=roles[user]
/admin.jsp=roles[admin]
# everything else requires authentication:
/** = authc
</value>
</property>
</bean>
- 配置ShiroFilter注意的点,因为filterChainDefinitions实质是保存的键值对,所以可以把数据保存在数据库。
realm的代码
package com.issimo.shiro.realms;
import java.util.HashSet;
import java.util.Set;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
public class ShiroRealm extends AuthorizingRealm {
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("I am coming!"+token);
//1.将AuthenticationToken 转换为UsernamePasswordToken
UsernamePasswordToken uptoken=(UsernamePasswordToken) token;
//2.从UsernamePasswordToken对象中取出username
String username=uptoken.getUsername();
//3.调用数据库方法,在数据库中查询username对应用户的记录
System.out.println("从数据库获取username相关的用户信息"+username+"所对应的用户信息");
//4.若用户不存在抛出UnKnownAccountException
if("unknown".equals(username)){
throw new UnknownAccountException("用户不存在");
}
//5.根据用户信息,决定是否抛出其他异常
if("moster".equals(username)){
throw new LockedAccountException("用户被锁定");
}
//根据用户的情况,来构建AuthenticationInfo对象 并返回!
//以下信息是从数据库获取的
//1).principal 认证的实体信息 可以说username 也可以是实体对象
Object principal=username;
//2).数据库中获取的密码
Object credentials=null; //"fc1709d0a95a6be30bc5926fdb7f22f4";
if("admin".equals(username)){
credentials="038bdaf98f2037b31f1e75b5b4c9b26e";
}else if("user".equals(username)){
credentials="098d2c478e9c11555ce2823231e02ec1";
}
//3).realmName: 当前realm对象的Name,调用父类的getName()方法即可!
String realmName=getName();
//使用颜值加密
ByteSource credentialsSalt=ByteSource.Util.bytes(username);
SimpleAuthenticationInfo info=null; //new SimpleAuthenticationInfo(principal, credentials, realmName);
info=new SimpleAuthenticationInfo(principal, credentials, credentialsSalt, realmName);
return info;
}
//授权会被shiro回调的方法
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection Principals) {
System.out.println("doGetAuthorizationInfo...");
//从PrincipalCollection获取用户登录的信息
Object principal=Principals.getPrimaryPrincipal();
//利用用户登录的信息来获取当前用户的角色或者权限(肯恶搞需要查询数据库)
Set<String> roles=new HashSet<>();
roles.add("user");
if("admin".equals(principal)){
roles.add("admin");
}
//创建SimpleAuthorizationInfo 设置其roles属性
SimpleAuthorizationInfo info =new SimpleAuthorizationInfo(roles);
//返回SimpleAuthorizationInfo对象
return info;
}
}
- Handler代码
- `package com.issimo.shiro.handlers;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
@RequestMapping(“/shiro”)
@Controller
public class ShiroHandler {
@RequestMapping("/login")
public String Login(@RequestParam("username") String username, @RequestParam("password") String password) {
Subject currentUser = SecurityUtils.getSubject();
if (!currentUser.isAuthenticated()) {
// 把用户名和密码封装为 UsernamePasswordToken 对象
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
// rememberme
token.setRememberMe(true);
try {
System.out.println("1. " + token.hashCode());
// 执行登录.
currentUser.login(token);
}
// ... catch more exceptions here (maybe custom ones specific to your application?
// 所有认证时异常的父类.
catch (AuthenticationException ae) {
//unexpected condition? error?
System.out.println("登录失败: " + ae.getMessage());
}
}
return "redirect:/list.jsp";
}
}
- 使用shiro三处可以连接数据库的地方:①filterChainDefinitions ②自定义的realms里的登录授权 ③ 自定义Realms里的角色授权
总体来说 确实很难,因为 里面的英文单词 太长太多,而且有些单词仅仅只差1个字母 比如 AuthorizationInfo,AuthenticationInfo
`
`