shiro简单介绍
shiro是一个功能强大的java安全框架,主要部分构成认证、授权、加密和会话管理等。
1.认证:身份认证,验证登录用户是否正确等。
2.授权:授予权利访问某个页面或接口。
3.加密:shiro提供加密服务。保护数据的安全性,如密码加密存储到数据库,而不是明文存储。
4.会话管理:用户登录了一次就是会话,在一定时间内,用户的所有信息都保存在会话中。
spring装配shiro,基于javaBean的写法
1.将SecurityManager交给spring处理
@Bean
public SecurityManager securityManager(){
DefaultWebSecurityManager securityManager=new DefaultWebSecurityManager();
securityManager.setRealm(shiroRealm());
return securityManager;
}
2.创建realm
@Bean
public ShiroRealm shiroRealm(){
ShiroRealm shiroRealm=new ShiroRealm();
return shiroRealm;
}
3.配置ShiroFilterFactoryBean
@Bean
public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager){
System.out.println("---shiroFIlter---");
ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();
shiroFilterFactoryBean.setSecurityManager(securityManager);
Map<String,String> filterChainDefinitionMap = new LinkedHashMap<>();
//注意过滤器配置顺序 不能颠倒
//配置退出 过滤器,其中的具体的退出代码Shiro已经替我们实现了,登出后跳转配置的loginUrl
// 配置不会被拦截的链接 顺序判断
filterChainDefinitionMap.put("/static/**", "anon");
filterChainDefinitionMap.put("/favicon.ico", "anon");
//拦截其他所以接口
filterChainDefinitionMap.put("/**", "authc");
//配置shiro默认登录界面地址,前后端分离中登录界面跳转应由前端路由控制,后台仅返回json数据
shiroFilterFactoryBean.setLoginUrl("/login");
// 登录成功后要跳转的链接 自行处理。不用shiro进行跳转
// shiroFilterFactoryBean.setSuccessUrl("user/index");
//未授权界面;
shiroFilterFactoryBean.setUnauthorizedUrl("/user/unauth");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
4.创建代理bean通知类和开起shiro aop切面编程支持,注:往spring里面注入这两个bean。才能用注解的方式去对权限做校验。
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator=new DefaultAdvisorAutoProxyCreator();
defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
return defaultAdvisorAutoProxyCreator;
}
/**
* 开启shiro aop注解支持
*/
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager){
AuthorizationAttributeSourceAdvisor sourceAdvisor=new AuthorizationAttributeSourceAdvisor();
sourceAdvisor.setSecurityManager(securityManager);
return sourceAdvisor;
}
自定义实现realm,实现认证和授权的过程
1.认证过程
认证我们需要做的是通过用户名的比对。从数据库中查询相应的用户。并放入SimpleAuthenticationInfo中,剩下的交给shiro去认证校验。
myrealm的认证:
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String username = (String)authenticationToken.getPrincipal();
System.out.println(username);
ShiroUser shiroUser=shiroUserMapper.selectByUserName(username);
if (shiroUser==null){
return null;
}
SimpleAuthenticationInfo authenticationInfo=new SimpleAuthenticationInfo(
shiroUser,
shiroUser.getPassword(),
getName()
);
return authenticationInfo;
}
}
查询语句:
<select id="selectByUserName" parameterType="java.lang.String" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from shiro_user
where username = #{userName,jdbcType=VARCHAR}
</select>
2.授权过程
授权需要我们做的是通过用户id查询角色和权限,将权限和角色注入到AuthorizationInfo
授权:
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("--权限注入--");
SimpleAuthorizationInfo simpleAuthorizationInfo=new SimpleAuthorizationInfo();
ShiroUser shiroUser= (ShiroUser) principalCollection.getPrimaryPrincipal();
//注入角色权限
try {
List<ShiroRole> shiroRoles=shiroUserMapper.selectRoleByUser(shiroUser.getId());
for (ShiroRole s:shiroRoles){
simpleAuthorizationInfo.addRole(s.getRoleName());
}
List<ShiroFunction> shiroFunctions =shiroUserMapper.queryByUserId(shiroUser.getId());
for(ShiroFunction functions:shiroFunctions){
simpleAuthorizationInfo.addStringPermission(functions.getPermissionName());
}
}catch (Exception e){
e.printStackTrace();
}
return simpleAuthorizationInfo;
}
查询语句:
<select id="selectRoleByUser" parameterType="java.lang.Integer" resultType="com.example.pojo.ShiroRole">
select role_name,role_id,shiro_role.create_time
from shiro_role
left join shiro_user_role r on shiro_role.id = r.role_id
left join shiro_user u on r.user_id = u.id
where u.id=#{id,jdbcType=INTEGER}
</select>
<select id="queryByUserId" parameterType="java.lang.Integer" resultType="com.example.pojo.ShiroFunction">
select shiro_function.id,shiro_function.create_time,shiro_function.function_name,shiro_function.permission_name,shiro_function.pid
from shiro_function
left join shiro_role_function r on shiro_function.id = r.function_id
left join shiro_user_role u on u.role_id = r.role_id
left join shiro_user su on u.user_id = su.id
where su.id=#{id,jdbcType=INTEGER}
</select>
结语:
这样一个简单的shiro权限的配置和注入就完成了,基本能够控制用户登录,根据用户的不用分配不同的权限和角色,达到对权限的控制。
demo地址:http://114.115.154.147/ 用户名:admin 密码:123 原谅没有域名。