一、用户登录的Controller控制层代码
@Controller
@RequestMapping("/")
public class LoginController {
@ResponseBody
@RequestMapping("doLogin")
public JsonResult doLogin(String username,
String password){
//对用户身份进行认证
//获取主体对象
Subject subject = SecurityUtils.getSubject();
//提交用户信息
UsernamePasswordToken token = new UsernamePasswordToken(username,password);
subject.login(token);
return new JsonResult("login ok");
}
}
二、获取用户信息(交给安全框架),并进行认证授权
写Realm类
/**
*Realm为Shiro框架中的核心业务组件之一
*通过此对象可以完成数据业务的获取以及封装
*/
@Service
public class ShiroUserRealm extends AuthorizingRealm{
@Autowired
private SysUserDao sysUserDao;
@Autowired
private SysRoleMenuDao sysRoleMenuDao;
@Autowired
private SysUserRoleDao sysUserRoleDao;
@Autowired
private SysMenuDao sysMenuDao;
/**
* 设置凭证(Credentials)匹配器
*/
@Override
public void setCredentialsMatcher(
CredentialsMatcher credentialsMatcher) {
HashedCredentialsMatcher cMatcher=new HashedCredentialsMatcher();
cMatcher.setHashAlgorithmName("MD5");
//设置加密的次数(这个次数应该与保存密码时那个加密次数一致)
//cMatcher.setHashIterations(5);
super.setCredentialsMatcher(cMatcher);
}
/**在此方法中完成认证信息的获取以及封装*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
//1.获取用户身份对象(例如用户名)
String username=(String)token.getPrincipal();
System.out.println("username="+username);
//2.基于用户名从数据库查询记录
SysUser user=sysUserDao.findUserByUserName(username);
//3.对查询结果进行验证,用户不存在则抛出异常
if(user==null)
throw new AuthenticationException("用户不存在");
if(user.getValid()==0)
throw new AuthenticationException("用户已被禁用");
//4.对数据库查询出的相关信息进行封装
ByteSource credentialsSalt=ByteSource.Util.bytes(user.getSalt());
SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(
user,//principal (身份对象)
user.getPassword(), //hashedCredentials(已加密的密码)
credentialsSalt,//credentialsSalt (盐)
this.getName());
//5.返回封装结果(传递给认证管理器)
return info;
}
/**在此方法中完成授权信息的获取以及封装*/
/**
*Realm为Shiro框架中的核心业务组件之一
*通过此对象可以完成数据业务的获取以及封装
*/
@Service
public class ShiroUserRealm extends AuthorizingRealm{
@Autowired
private SysUserDao sysUserDao;
@Autowired
private SysRoleMenuDao sysRoleMenuDao;
@Autowired
private SysUserRoleDao sysUserRoleDao;
@Autowired
private SysMenuDao sysMenuDao;
/**
* 设置凭证(Credentials)匹配器
*/
@Override
public void setCredentialsMatcher(
CredentialsMatcher credentialsMatcher) {
HashedCredentialsMatcher cMatcher=new HashedCredentialsMatcher();
cMatcher.setHashAlgorithmName("MD5");
//设置加密的次数(这个次数应该与保存密码时那个加密次数一致)
//cMatcher.setHashIterations(5);
super.setCredentialsMatcher(cMatcher);
}
/**在此方法中完成认证信息的获取以及封装*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(
AuthenticationToken token) throws AuthenticationException {
//1.获取用户身份对象(例如用户名)
String username=(String)token.getPrincipal();
System.out.println("username="+username);
//2.基于用户名从数据库查询记录
SysUser user=sysUserDao.findUserByUserName(username);
//3.对查询结果进行验证,用户不存在则抛出异常
if(user==null)
throw new AuthenticationException("用户不存在");
if(user.getValid()==0)
throw new AuthenticationException("用户已被禁用");
//4.对数据库查询出的相关信息进行封装
ByteSource credentialsSalt=ByteSource.Util.bytes(user.getSalt());
SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(
user,//principal (身份对象)
user.getPassword(), //hashedCredentials(已加密的密码)
credentialsSalt,//credentialsSalt (盐)
this.getName());
//5.返回封装结果(传递给认证管理器)
return info;
}
/**在此方法中完成授权信息的获取以及封装*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(
PrincipalCollection principals) {
System.out.println("doGetAuthorizationInfo");
//1.获取登录用户具有的权限信息
//1.1获取用户身份对象
SysUser user=(SysUser)principals.getPrimaryPrincipal();
//1.2基于用户id获取角色id(可能多个):查中间表sys_user_roles;
List<Integer> roleIds=sysUserRoleDao.findRoleIdsByUserId(user.getId());
//1.3基于角色id获取菜单id(可能多个):查中间表sys_role_menus
List<Integer> menuIds=sysRoleMenuDao.findMenuIdsByRoleId(
roleIds.toArray(new Integer[]{}));
//1.4基于菜单id获取权限标识(sys:user:valid):查询菜单表sys_menus;
List<String> permissions=sysMenuDao.findPermissions(
menuIds.toArray(new Integer[]{}));
//2.对权限信息封装
SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
//3.返回封装结果(授权管理器);
Set<String> set=new HashSet<>();
for(String per:permissions){
if(!StringUtils.isEmpty(per)){
set.add(per);
}
}
info.setStringPermissions(set);
return info;
}
}
三、将身份交给realm
@Configuration
public class AppShiroConfig {
/**
* 配置shiro的SecurityManager对象
*/
@Bean("securityManager")
public SecurityManager newSecurityManager(
AuthorizingRealm realm){
DefaultWebSecurityManager sManager = new DefaultWebSecurityManager();
//通过reaml访问数据库
sManager.setRealm(realm);
return sManager;
}
SysUserRoleMapper中元素定义
<select id="findRoleIdsByUserId"
resultType="int">
select role_id
from sys_user_roles
where user_id=#{userId}
</select>
SysRoleMenuMapper中元素定义
<select id="findMenuIdsByRoleId"
resultType="int">
select menu_id
from sys_role_menus
where role_id in
<foreach collection="roleIds"
open="("
close=")"
separator=","
item="item">
#{item}
</foreach>
</select>
SysMenuMapper中元素定义
<select id="findPermissions"
resultType="string">
select permission <!-- sys:user:update -->
from sys_menus
where id in
<foreach collection="menuIds"
open="("
close=")"
separator=","
item="item">
#{item}
</foreach>
</select>
授权检测实现
在需要进行授权检测的方法上添加执行此方法需要的权限标识
例如
@RequestPermissions(“sys:user:valid”)