前端从后端剥离,形成一个前端工程,前端只利用Json来和后端进行交互,后端不返回页面,只返回Json数据。前后端之间完全通过public API约定。
1 自定义Realms
Shiro从Realm获取安全数据(如用户、角色、权限):就是说SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较以确定用户身份是否合法;也需要从Realm得到用户相应的角色/权限进行验证用户是否能进行操作;可以把Realm看成DataSource,即安全数据源。
doGetAuthorizationInfo()方法用于控制用户权限获取。
doGetAuthenticationInfo()方法用于控制用户登录。
在项目包下建一个ShiroRealm类,继承AuthorizingRealm抽象类。
public class ShiroRealm extends AuthorizingRealm {
private static final Logger logger = LoggerFactory.getLogger(ShiroRealm.class);
@Autowired
MemberService memberService;
@Autowired
PermissionService permissionService;
/**
* 获取身份信息,我们可以在这个方法中,从数据库获取该用户的权限和角色信息
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
ShiroUser shiroUser = (ShiroUser) principals.getPrimaryPrincipal();
SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
Set<String> roles = Sets.newHashSet();
Set<String> permissions = Sets.newHashSet();
List<Integer> pIdList =null;
try
{
pIdList = permissionService.findPermissionIdByMemberId(UserUtils.getCurrrentUserId());
}catch(Exception e)
{
e.printStackTrace();
}
if (!GeneralUtil.isEmpty(pIdList))
{
for (int pid: pIdList)
{
permissions.add(pid+"");
}
}
authorizationInfo.setRoles(roles);
authorizationInfo.setStringPermissions(permissions);
return authorizationInfo;
}
/**
* 在这个方法中,进行身份验证
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//CaptchaUsernamePasswordToken token = (CaptchaUsernamePasswordToken) authenticationToken;
String username = (String) authenticationToken.getPrincipal();
String captcha = null;
Object obj_captcha = SecurityUtils.getSubject().getSession()
.getAttribute("captchaCode");
String ip = null;
Object obj_ip = SecurityUtils.getSubject().getSession()
.getAttribute("captchaCodeIp");
if (obj_ip instanceof String) {
ip = (String) obj_ip;
}
Member member =this.memberService.findUserByUserLoginName(username);
if (member == null) {
return null;
}
return new SimpleAuthenticationInfo(
//new ShiroUser(user.getId(), user.getLoginName(), user.getLoginName()),
new ShiroUser(member.getId().longValue(), member.getUserName(), member.getUserName()),
member.getPassword(), //密码
new SimpleByteSource(member.getUserName()),//salt=username
getName() //realm name
);
}
}
2Shiro的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:util="http://www.springframework.org/schema/util" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">
<!-- 缓存管理器 使用Ehcache实现 -->
<bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager">
<property name="cacheManagerConfigFile" value="classpath:ehcache.xml"/>
</bean>
<!-- 凭证匹配器 -->
<bean id="credentialsMatcher"
class="cn.suyan.shiro.credentials.RetryLimitHashedCredentialsMatcher">
<constructor-arg ref="cacheManager"/>
<property name="hashAlgorithmName" value="md5"/>
<property name="hashIterations" value="2"/>
<property name="storedCredentialsHexEncoded" value="true"/>
</bean>
<!-- Realm实现 -->
<bean id="shiroRealm" class=