Maven中引入Shiro依赖
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.7.0</version>
</dependency>
<-- shiro整合Thymeleaf模板的依赖-->
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
<--导入这个依赖之后在shiro的配置文件中加入下段代码
/* shiro方言 让thymeleaf支持shiro标签
* @return
*/
@Bean
public ShiroDialect shiroDialect() {
return new ShiroDialect();
}
-->
ShiroConfig配置文件
package com.lwk.shiro.config;
import at.pollux.thymeleaf.shiro.dialect.ShiroDialect;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.codec.Base64;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;
import java.util.Map;
@Configuration
public class ShiroConfig {
//shiro拦截器
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
//设置安全管理器
bean.setSecurityManager(defaultWebSecurityManager);
//添加shiro内置过滤器
/*
anon 无需认证就能访问
authc 必须认证才能访问
user 必须使用记住我功能才能访问
perms 拥有对某个资源的权限才能访问
*/
Map<String, String> filterMap = new LinkedHashMap<>();
filterMap.put("/shiro/*", "anon");//例:/shiro路径下的所有资源无需认证就能访问
filterMap.put("/signUp", "anon");
filterMap.put("/**", "authc");//拦截所有资源
bean.setUnauthorizedUrl("/"); //未通过认证跳转到的页面
bean.setLoginUrl("/"); //设置默认登录页面
bean.setFilterChainDefinitionMap(filterMap);//注入拦截资源的Map
return bean;
}
/**
* 配置核心安全事务管理器
*
* @param userRealm
* @return
*/
@Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//关联UserRealm
securityManager.setRealm(userRealm);
securityManager.setRememberMeManager(rememberMeManager());
securityManager.setSessionManager(mySessionManager());
return securityManager;
}
/**
* 配置shiro 的session管理 相当于 HttpServletSession
*
*
* @return
*/
@Bean
public DefaultWebSessionManager mySessionManager(){
DefaultWebSessionManager defaultSessionManager = new DefaultWebSessionManager();
defaultSessionManager.setSessionValidationSchedulerEnabled(false);
//将sessionIdUrlRewritingEnabled属性设置成false
defaultSessionManager.setSessionIdUrlRewritingEnabled(false);
defaultSessionManager.setGlobalSessionTimeout(1000*60*60*24);
return defaultSessionManager;
}
//创建realm对象,自定义类
@Bean(name = "userRealm")
public UserRealm userRealm() {
return new UserRealm();
}
/**
* cookie管理对象;记住我功能,rememberMe管理器
*
* @return
*/
@Bean
public CookieRememberMeManager rememberMeManager() {
CookieRememberMeManager cookieRememberMeManager = new CookieRememberMeManager();
cookieRememberMeManager.setCookie(simpleCookie());
//rememberMe cookie加密的密钥 建议每个项目都不一样 默认AES算法 密钥长度(128 256 512 位)
cookieRememberMeManager.setCipherKey(Base64.decode("4AvVhmFLUs0KTA3Kprsdag=="));
return cookieRememberMeManager;
}
/**
* FormAuthenticationFilter 过滤器 过滤记住我
*
* @return
*/
@Bean
public FormAuthenticationFilter formAuthenticationFilter() {
FormAuthenticationFilter formAuthenticationFilter = new FormAuthenticationFilter();
//对应前端的checkbox的name = rememberMe
formAuthenticationFilter.setRememberMeParam("rememberMe");
return formAuthenticationFilter;
}
/**
* cookie对象;会话Cookie模板 ,默认为: JSESSIONID 问题: 与SERVLET容器名冲突,重新定义为sid或rememberMe,自定义
*
* @return
*/
@Bean
public SimpleCookie simpleCookie() {
//这个参数是cookie的名称,对应前端的checkbox的name = rememberMe
SimpleCookie simpleCookie = new SimpleCookie("rememberMe");
//setcookie的httponly属性如果设为true的话,会增加对xss防护的安全系数。它有以下特点:
//setcookie()的第七个参数
//设为true后,只能通过http访问,javascript无法访问
//防止xss读取cookie
simpleCookie.setHttpOnly(true);
simpleCookie.setPath("/");
simpleCookie.setMaxAge(60 * 60 * 24 * 15);
return simpleCookie;
}
}
创建自己的UserRealm类
package com.lwk.shiro.config;
import org.apache.shiro.authc.*;
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;
import org.springframework.beans.factory.annotation.Autowired;
public class UserRealm extends AuthorizingRealm {
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//拿到当前登录的对象
return info;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//1.把AuthenticationToken转换为UsernamePasswordToken
//usernamePasswordToken 中保存着前端用户输入的用户名或者密码和是否记住我(例如 admin 123 false)
UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) authenticationToken;
//2.从usernamePasswordToken中获取username
String username=usernamePasswordToken.getUsername();
//3.调用方法从数据库中获取用户信息
String usernmae= xxx;//我这里查的用户名
//4.用户不存在的时候抛出UnknownException
if (uasername==null){//这里可以自己抛出shiro中的异常,看自己需求
throw new UnknownAccountException("用户不存在");
}
//5.根据用户情况 来构建AuthenticationInfo对象并返回
//5.1.principal:认证的实体信息,可以是username,也可以是用户对应数据库的实体配
Object principal=username;
//5.2.credentials:密码
Object credentials=xxx;//数据库中获取用户的密码
//5.3.realmName: 当前realm对象的name,调用父类的getName即可
SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(principal,credentials,getName() );
return info;
}
}
UserController中使用shiro的登录
package com.lwk.shiro.controller;
import com.lwk.shiro.pojo.User;
import com.lwk.shiro.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.CredentialsMatcher;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Controller
@RequestMapping("/shiro")
public class UserController {
@Autowired
private UserService userService;
@Autowired
private HttpServletResponse response;
@ResponseBody
@RequestMapping(value = "login", method = RequestMethod.POST)
public String login(User user) {
if (user == null) {
return "账号密码不能为空";
}
UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword(), false);
Subject subject = SecurityUtils.getSubject();
//登录验证这里可以捕获到shiro的异常并反馈信息
//这些异常可以根据自己的需要来处理
try {
subject.login(token);
} catch (UnknownAccountException uae) {//账号不存在
return uae.getMessage();
} catch (IncorrectCredentialsException ice) {//登录信息验证错误
return "账号密码错误";
}
try {
response.sendRedirect("/index");
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
//这里可以使用shiro的登出(注销登陆)
@RequestMapping("logout")
public String logout() {
Subject subject = SecurityUtils.getSubject();
subject.logout();
return "redirect:/";
}
}
使用shiro登陆之后可以通过下面这句代码拿到 登录的 user对象
User user = (User) subject.getPrincipal();