springboot 集成 shiro 盐值加密

voaycc 2019-02-28 11:40:43
记录一下自己集成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("/login/logout","logout");
// filterChainDefinitionMap.put("/css","anon");
// filterChainDefinitionMap.put("/js","anon");
// filterChainDefinitionMap.put("/fonts","anon");
// filterChainDefinitionMap.put("/images","anon");
// filterChainDefinitionMap.put("/img","anon");
// filterChainDefinitionMap.put("/static/**", "anon");
//对所有用户认证
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(VerityUtil.ALGORITHMNAME);
// 设置散列次数: 意为加密几次
hashedCredentialsMatcher.setHashIterations(VerityUtil.HASHITERATIONS);

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 {
List<Permission> permissions = iAdminService.getAdminMenus(admin.getId());
httpSession.setAttribute("admin",admin);
httpSession.setAttribute("menus",permissions);
VerityUtil.setCunrrentAdmin(httpSession,admin);
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 );
return simpleAuthenticationInfo;
}catch (Throwable t){
throw new AuthenticationException();
}

}
}

// /**
// * 设定Password校验.
// */
// @PostConstruct
// public void initCredentialsMatcher() {
// //该句作用是重写shiro的密码验证,让shiro用我自己的验证
// setCredentialsMatcher(new CustomCredentialsMatcher());
//
// }


}



4.加密类

public class VerityUtil {

public static String SALT_STR = "salt";
public static String PASSWORD_STR = "password";
public static String LOGIN_NAME_STR = "loginName";
//加密方式
public static String ALGORITHMNAME = "md5";
//加密次数
public static int HASHITERATIONS = 2;

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(
ALGORITHMNAME,
userFormMap.get(PASSWORD_STR),
ByteSource.Util.bytes(userFormMap.get(LOGIN_NAME_STR) + salt),
HASHITERATIONS
).toHex();
userFormMap.put(PASSWORD_STR, newPassword);
}

}


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);
} 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";
}

}
...全文
109 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

81,091

社区成员

发帖
与我相关
我的任务
社区描述
Java Web 开发
社区管理员
  • Web 开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧