Shiro配置及获取用户工具类
本学期做了一个项目,利用了Shiro这个安全框架来做身份验证和权限管理。以本文章记录一下项目中使用的Shiro配置及获取当前用户信息的工具类和一个简单的MD5密码加密工具类。
获取用户信息的工具类主要是利用Shiro中自带的Session,在项目中都可以直接使用该工具类获取当前用户信息。
shiro配置类
ps:下面添加的userRealm,adminRealm,communityRealm都是项目中自定义的3个身份Realm,分别为用普通用户、管理员和社团用户
@Configuration
public class ShiroConfig {
//创建Realm对象
@Bean
public UserRealm userRealm(){
return new UserRealm();//返回自己定义的类
}
@Bean
public AdminRealm adminRealm(){ return new AdminRealm();}
@Bean
public CommunityRealm communityRealm() { return new CommunityRealm();}
@Bean(name="securityManager")
// 2.创建DefaultSecurityManager @Qualifier:指定方法名字 此时UserRealm已经被Spring托管
public DefaultSecurityManager getDefaultSecurityManager(@Qualifier("userRealm") UserRealm userRealm, @Qualifier("adminRealm") AdminRealm adminRealm,@Qualifier("communityRealm")CommunityRealm communityRealm){
DefaultWebSecurityManager defaultSecurityManager = new DefaultWebSecurityManager();
//管理Realm
Collection<Realm> realms = new ArrayList<>();
realms.add(userRealm);
realms.add(adminRealm);
realms.add(communityRealm);
defaultSecurityManager.setRealms(realms);
//当然也可以继续增加别的Realm....
//defaultSecurityManager.setRealm(communityRealm);
//ThreadContext.bind(defaultSecurityManager);
return defaultSecurityManager;
}
//3.设置授权、过滤器
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultSecurityManager securityManager){
//过滤器工厂
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
//设置安全管理器
bean.setSecurityManager(securityManager);
//来添加shiro的内置过滤器
/*
anon: 无需认证即可访问
authc: 必须认证才能用x
user: 必须拥有 “记住我” 功能才能用
perms: 拥有对某个资源的权限才能用
role: 拥有某个角色权限才能访问
*/
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
ShiroFilterFactoryBean filterFactory = new ShiroFilterFactoryBean();
Map<String, Filter> filters = filterFactory.getFilters();
filters.put("authc", new AuthenticationFilter());
bean.setFilters(filters);
//先设置授权
//===================设置授权======================
//user用户 且有add权限,才能访问
//filterChainDefinitionMap.put("/user/add","perms[user:add]");
//user用户 且有update权限,才能访问
//filterChainDefinitionMap.put("/user/update","perms[user:update");
//===================设置拦截======================
//设置首页 : 无需认证即可访问
//filterChainDefinitionMap.put("/login","anon");
//设置其他页面:需要认证才能访问 (此时是user包下的所有html)
//filterChainDefinitionMap.put("/user/*","authc");
bean.setFilterChainDefinitionMap(filterChainDefinitionMap);
// //设置用户如果未登录
// bean.setLoginUrl("/toLogin");
//
// //设置未授权的跳转页面
// bean.setUnauthorizedUrl("/toLogin");
return bean;
}
/**
* 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions)
* 配置以下两个bean(DefaultAdvisorAutoProxyCreator和AuthorizationAttributeSourceAdvisor)即可实现此功能
* @return DefaultAdvisorAutoProxyCreator
*/
@Bean
public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
advisorAutoProxyCreator.setProxyTargetClass(true);
return advisorAutoProxyCreator;
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
return authorizationAttributeSourceAdvisor;
}
}
普通用户的配置:
public class UserRealm extends AuthorizingRealm {
@Autowired
UserServiceImpl userService;
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
//如果进入一些需要授权的页面,就会进入这个方法
System.out.println("执行用户授权");
//拿到当前登录的对象
Subject subject = SecurityUtils.getSubject();
Session session = subject.getSession();
User user = (User) session.getAttribute("user");
//如果当前用户不是普通用户,不授权
if(user.getUserRole() != USER){
return null;
}
//封装角色信息
Set<String> roles = new HashSet<>();
roles.add("user");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);
System.out.println("普通用户授权完成");
//返回的是info
return info;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("执行普通用户认证");
//这是用户登录的token 将它转换为UsernamePasswordToken
UsernamePasswordToken userToken = (UsernamePasswordToken) token;
//获取用户信息
User user = userService.queryUserByName(userToken.getUsername());
if(user==null){
System.out.println("用户名不正确");
return null;
}
if(user.getUserRole() != USER){
return null;
}
System.out.println("普通用户认证成功");
//如果用户认证成功,Session中保存该用户
Subject subject = SecurityUtils.getSubject();
Session session = subject.getSession();
session.setAttribute("user",user);
//如果用户名正确,让shiro来执行密码认证,注意密码加密
//1)principal:认证的实体信息,可以是username,也可以是数据库表对应的用户的实体对象
Object principal = user.getUserName();
//2)credentials:密码
Object credentials = ((UsernamePasswordToken) token).getPassword();
//3)realmName:当前realm对象的name,调用父类的getName()方法即可
String realmName = getName();
//4)credentialsSalt盐值
ByteSource credentialsSalt = ByteSource.Util.bytes(principal);//使用账号作为盐值
return new SimpleAuthenticationInfo(principal, credentials, credentialsSalt,realmName);
}
}
UserUtils工具类
@Component
public class UserUtils {
//直接获取当前用户
public User getUser(){
Subject subject = SecurityUtils.getSubject();
Session session = subject.getSession();
return (User) session.getAttribute("user");
}
//获取用户姓名
public String getUserName(){
return getUser().getUserName();
}
//获取用户id
public int getUserId(){
return getUser().getUserId();
}
//获取用户头像
public String getUserAvatar(){
return getUser().getUserAvatar();
}
//获取用户描述
public String getUserDescription(){
return getUser().getUserDescription();
}
//获取用户身份
public int getUserRole(){
return getUser().getUserRole();
}
//获取用户Email
public String getUserEmail(){
return getUser().getUserEmail();
}
//获取用户密码
public String getUserx(){
return getUser().getUserPassword();
}
}
最后用到了一个MD5加密密码的算法,同样也封装成了工具类,可以直接使用。
@Component
public class MD5Utils {
public String MD5EncryptPassword(String userName,String password){
String hashAlgorithmName = "MD5";//加密方式
ByteSource salt = ByteSource.Util.bytes(userName);//以账号作为盐值
int hashIterations = 1024;//加密1024次
String newPassword = String.valueOf(new SimpleHash(hashAlgorithmName, password,salt,hashIterations));
return newPassword;
}
}