记录一下自己集成shiro的步骤,也是第一次使用,很多地方比较生硬
1.导入pom包
<!-- shiro -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
2.配置shiro
@Configuration
public class ShiroConfiguration {
//将自己的验证方式加入容器
@Bean
public MyShiroRealm myShiroRealm() {
MyShiroRealm myShiroRealm = new MyShiroRealm();
myShiroRealm.setCredentialsMatcher(hashedCredentialsMatcher());
return myShiroRealm;
}
//权限管理,配置主要是Realm的管理认证
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myShiroRealm());
return securityManager;
}
//Filter工厂,设置对应的过滤条件和跳转条件
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String,String> filterChainDefinitionMap = new HashMap<String, String>();
//对所有用户认证
filterChainDefinitionMap.put("/plat/**","authc");
filterChainDefinitionMap.put("/index/**","authc");
//登录
shiroFilterFactoryBean.setLoginUrl("/login");
//首页
shiroFilterFactoryBean.setSuccessUrl("/index");
//错误页面,认证不通过跳转
shiroFilterFactoryBean.setUnauthorizedUrl("/login");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
//设置默认加密方式
@Bean
public HashedCredentialsMatcher hashedCredentialsMatcher(){
HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
// 使用md5 算法进行加密
hashedCredentialsMatcher.setHashAlgorithmName(ShiroVerityUtil.ALGORITHM_NAME);
// 设置散列次数: 意为加密几次
hashedCredentialsMatcher.setHashIterations(ShiroVerityUtil.HASH_ITERATIONS);
return hashedCredentialsMatcher;
}
//加入注解的使用,不加入这个注解不生效
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
}
3.编写实现realm
//实现AuthorizingRealm接口用户用户认证
public class MyShiroRealm extends AuthorizingRealm {
//用于用户查询
@Autowired
private IAdminService iAdminService;
//角色权限和对应权限添加
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//获取登录用户名
String username = (String) principalCollection.getPrimaryPrincipal();
//查询用户名称
QueryWrapper<Admin> adminQueryWrapper = new QueryWrapper<>();
adminQueryWrapper.lambda().eq(Admin::getLoginName, username);
Admin admin = iAdminService.getOne(adminQueryWrapper);
//添加角色和权限
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
for (Role role : admin.getRoles()) {
//添加角色
simpleAuthorizationInfo.addRole(role.getName());
for (Permission permission : role.getPermissions()) {
//添加权限
simpleAuthorizationInfo.addStringPermission(permission.getName());
}
}
return simpleAuthorizationInfo;
}
//用户认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
Subject subject = SecurityUtils.getSubject();
Session httpSession = subject.getSession();
//加这一步的目的是在Post请求的时候会先进认证,然后在到请求
if (authenticationToken.getPrincipal() == null) {
return null;
}
//获取用户信息
String username = authenticationToken.getPrincipal().toString();
//查询用户名称
QueryWrapper<Admin> adminQueryWrapper = new QueryWrapper<>();
adminQueryWrapper.lambda().eq(Admin::getLoginName, username);
Admin admin = iAdminService.getOne(adminQueryWrapper);
if (admin == null) {
//这里返回后会报出对应异常
throw new UnknownAccountException();
} else {
String password = admin.getPassword();
ByteSource salt = ByteSource.Util.bytes(admin.getLoginName() + admin.getSalt());
String realmName = getName();
try{
//这里验证authenticationToken和simpleAuthenticationInfo的信息
SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo( username, password, salt, realmName );
//验证通过后,注入对象
List<Permission> permissions = iAdminService.getAdminMenus(admin.getId());
httpSession.setAttribute("admin",admin);
httpSession.setAttribute("menus",permissions);
httpSession.setTimeout(ShiroVerityUtil.SESSION_TIME_OUT);
ShiroVerityUtil.setCunrrentAdmin(admin);
return simpleAuthenticationInfo;
}catch (Throwable t){
throw new AuthenticationException();
}
}
}
}
4.加密类
public class ShiroVerityUtil {
public static String SALT_STR = "salt";
public static String PASSWORD_STR = "password";
public static String LOGIN_NAME_STR = "loginName";
//加密方式
public static String ALGORITHM_NAME = "md5";
//加密次数
public static int HASH_ITERATIONS = 2;
//session过期时间 ms
public static int SESSION_TIME_OUT = 5 * 60 * 1000;
private static RandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator();
/**
* shiro 盐值加密
*/
public static void encryptPassword(Map userFormMap) {
String salt = MapUtils.getString(userFormMap, SALT_STR);
if (StringUtils.isBlank(salt)) {
salt = randomNumberGenerator.nextBytes().toHex();
userFormMap.put(SALT_STR, salt);
}
String newPassword = new SimpleHash(
ALGORITHM_NAME,
userFormMap.get(PASSWORD_STR),
ByteSource.Util.bytes(userFormMap.get(LOGIN_NAME_STR) + salt),
HASH_ITERATIONS
).toHex();
userFormMap.put(PASSWORD_STR, newPassword);
}
/**
* @return
* @Title: getCunrrentAdminSyBranch
* @Description: 获得登录人的分部
* @author: zhenglei
* @date: 2018年9月7日 上午10:00:17
*/
public static JsonResult getCunrrentAdminSyBranch() {
JsonResult b = new JsonResult();
Admin cunrrentAdmin = ShiroVerityUtil.getCunrrentAdmin();
if (cunrrentAdmin == null) {
b.setFailInfo500();
b.setMessage(CommonText.NOT_LOGIN);
return b;
}
String syBranch = cunrrentAdmin.getSyBranch();
if (StringUtils.isBlank(syBranch)) {
b.setFailInfo500();
b.setMessage(CommonText.NOT_LOGIN);
return b;
}
b.setData(syBranch);
return b;
}
/**
* @return
* @Title: getCunrrentAdmin
* @Description: 获得当前登录人
* @author: zhenglei
* @date: 2018年9月5日 下午2:33:47
*/
public static Admin getCunrrentAdmin() {
Subject subject = SecurityUtils.getSubject();
Session httpSession = subject.getSession();
Object attribute = httpSession.getAttribute(SystemConstant.ADMIN_SESSION);
if (attribute == null) {
return null;
}
return (Admin) attribute;
}
/**
* @return
* @Title: setCunrrentAdmin
* @Description: 获设置当前登录人
* @author: zhenglei
* @date: 2018年9月5日 下午2:33:47
*/
public static void setCunrrentAdmin(Admin admin) {
Subject subject = SecurityUtils.getSubject();
Session httpSession = subject.getSession();
httpSession.setAttribute(SystemConstant.ADMIN_SESSION, admin);
}
}
5.登录loginController编辑
@Controller
@RequestMapping("/login")
public class LoginController {
@GetMapping("")
public String login() {
return "login";
}
@GetMapping("logout")
public String logout() {
Subject subject = SecurityUtils.getSubject();
subject.logout();
return "/login";
}
@PostMapping("/postLogin")
public String postLogin(String username, String password){
//添加用户认证信息
Subject subject = SecurityUtils.getSubject();
Session session = subject.getSession();
UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username,password);
try {
// 执行登陆
subject.login(usernamePasswordToken);
subject.isPermitted();
} catch ( UnknownAccountException e ) {
session.setAttribute(CommonText.LOGIN_ERR_MSG,CommonText.ACCOUNT_DOES_NOT_EXIST);
return "redirect:/login";
} catch ( IncorrectCredentialsException e ) {
session.setAttribute(CommonText.LOGIN_ERR_MSG,CommonText.PASSWORD_DOES_NOT_CORRECT);
return "redirect:/login";
} catch ( LockedAccountException e ) {
session.setAttribute(CommonText.LOGIN_ERR_MSG,CommonText.ADMIN_DOES_NOT_EXIST);
return "redirect:/login";
} catch ( ExcessiveAttemptsException e ) {
session.setAttribute(CommonText.LOGIN_ERR_MSG,CommonText.MORT_TIME_TRY);
return "redirect:/login";
}
return "redirect:/index";
}
}