1. 引入相关依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</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-spring</artifactId>
<version>1.3.2</version>
</dependency>
2. 配置Shiro的核心过滤器
@Configuration
public class ShiroFilterConf {
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(SecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
//过滤器链的集合 AnonymousFilter 匿名过滤器 anon
//FormAuthenticationFilter 认证过滤器 authc
Map<String, String> map = new HashMap<>();
map.put("/admin/loginAdmin","anon");
map.put("/code/getCode","anon");
//放行login文件夹下的所有资源,有静态资源样式,不放行样式会消失
map.put("/login/**","anon");
map.put("/**","authc");
shiroFilterFactoryBean.setLoginUrl("/login/login.jsp");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
@Bean
public SecurityManager getSecurityManager( MyRealm myRealm,EhCacheManager ehCacheManager){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setCacheManager(ehCacheManager);
securityManager.setRealm(myRealm);
return securityManager;
}
@Bean
public MyRealm getMyRealm(CredentialsMatcher credentialsMatcher){
MyRealm myRealm = new MyRealm();
myRealm.setCredentialsMatcher(credentialsMatcher);
return myRealm;
}
@Bean
public CredentialsMatcher getCredentialsMatcher(){
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
// 加密算法 和 散列次数
hashedCredentialsMatcher.setHashAlgorithmName("md5");
hashedCredentialsMatcher.setHashIterations(1024);
return hashedCredentialsMatcher;
}
@Bean
public EhCacheManager getEhCatch(){
EhCacheManager ehCacheManager = new EhCacheManager();
return ehCacheManager;
}
}
3. 自定义MyRealm
//AuthorizingRealm 继承了 AuthenticatingRealm
public class MyRealm extends AuthorizingRealm {
@Autowired
private AdminService adminService;
@Override //授权
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("===================");
//通过用户名查主体 通过主体查角色 通过角色查权限
String principal = (String) principalCollection.getPrimaryPrincipal();
//查数据库
Map<String, Object> map = new HashMap<>();
map.put("name", principal);
List<Admin> admins = adminService.selectByMap(map);
if (admins.size() != 0) {
Admin admin = admins.get(0);
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
authorizationInfo.addRole(admin.getLevel());
//如果是超级管理员 拥有删除用户的权利 这里这样写是因为前台用的 JqGrid <shiro:hasPermission name="user:delete">del:false,</shiro:hasPermission>
if ("super".equals(admin.getLevel())) {
authorizationInfo.addStringPermission("user:add");
authorizationInfo.addStringPermission("user:update");
authorizationInfo.addStringPermission("user:query");
}else{
authorizationInfo.addStringPermission("user:add");
authorizationInfo.addStringPermission("user:delete");
authorizationInfo.addStringPermission("user:update");
authorizationInfo.addStringPermission("user:query");
}
return authorizationInfo;
}
return null;
}
@Override //认证
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String principal = (String) authenticationToken.getPrincipal();
//查数据库 获取User对象 判断user对象是否为空 不为空 封装一个AuthenticationInfo返回
//查数据库
Map<String, Object> map = new HashMap<>();
map.put("name", principal);
List<Admin> admins = adminService.selectByMap(map);
if (admins.size() != 0) {
Admin admin = admins.get(0);
AuthenticationInfo authenticationInfo =
new SimpleAuthenticationInfo(admin.getName(), admin.getPassword(), ByteSource.Util.bytes(""), this.getName());
return authenticationInfo;
}
return null;
}
}
4. Controller 中
//shiro登录验证
@RequestMapping("loginAdmin")
public Map<String,Object> LoginUser(String username, String password, String code, HttpServletRequest request) {
//获得验证码
String validationCode = (String) request.getSession().getAttribute("code");
if (!validationCode.equalsIgnoreCase(code)) {
return setResultErrorMsg("验证码错误");
}
//shiro判断用户名和密码
Subject subject = SecurityUtils.getSubject();
AuthenticationToken token = new UsernamePasswordToken(username, password);
try {
subject.login(token);
Map<String, Object> map = BaseApiService.setResultSuccess();
return map;
} catch (UnknownAccountException e) {
System.out.println("用户名不正确");
return setResultErrorMsg("用户名不正确");
} catch (IncorrectCredentialsException e) {
System.out.println("密码错误");
return setResultErrorMsg("密码错误");
}
}
//退出时shiro清除登录session
@RequestMapping("logoutAdmin")
public String LogoutUser() {
Subject subject = SecurityUtils.getSubject();
subject.logout();
return "ok";
}
5. 前台的 Shiro 相关标签
<shiro:principal></shiro:principal> //用户的身份信息
<shiro:authenticated></shiro:authenticated> //认证成功 执行标签体的内容
<shiro:notAuthenticated></shiro:notAuthenticated> //未认证 执行标签体内容
//基于角色的权限管理
<shiro:hasRole name="super"></shiro:hasRole>
<shiro:hasAnyRoles name="admin,super"></shiro:hasAnyRoles>
//基于资源的权限管理
<shiro:hasPermission name="user:delete"></shiro:hasPermission>