1.用户与角色的关系(多对多,又是特殊做法- -)
为了给用户添加角色要使用映射,类型是多对多。
又使用联合主键映射的原因:
1.User类与映射文件被写死,没有权限去修改架构师写好的代码,不能修改类结构与配置文件
2.为了以后功能扩展方便(待体验)
User类本身不做任何修改!
联合主键类+主键类
public class UserRole implements Serializable {
private UserRoleId id;
也可以吧userId改写成User,但没有必要,会加大加载负担
public class UserRoleId implements Serializable {
private Role role;
private String userId;
hibernate配置
<hibernate-mapping>
<class name="com.vincent.ssh.user.entity.UserRole" table="user_role" catalog="ssh">
<composite-id name="id" class="com.vincent.ssh.user.entity.UserRoleId">
<key-many-to-one name="role" lazy="false" class="com.vincent.ssh.role.entity.Role">
<!-- 映射类本身,但数据库只保存id字段 -->
<column name="role_id"></column>
</key-many-to-one>
<key-property name="userId" type="string">
<column name="user_id" length="32"></column>
</key-property>
</composite-id>
</class>
</hibernate-mapping>
因为是单方面的映射,所以底层Dao业务要自己写查询以外语句
public void saveUserRole(UserRole userRole) {
// TODO Auto-generated method stub
getHibernateTemplate().save(userRole);
}
//清除用户的所有权限字段,为了解决编辑时的逻辑问题
public void cleanUserRoleById(Serializable id) {
// TODO Auto-generated method stub
String hql = "DELETE FROM UserRole WHERE id.userId = ?0";
currentSession().createQuery(hql).setParameter(0, id).executeUpdate();
}
public List<UserRole> getUserRoleById(String id) {
// TODO Auto-generated method stub
String hql = "FROM UserRole WHERE id.userId = ?0";
return currentSession().createQuery(hql).setParameter(0, id).list();
}
public List<User> findUserByAccountAndPass(String account, String password) {
// TODO Auto-generated method stub
String hql = "FROM User WHERE account = ?0 AND password = ?1";
return currentSession().createQuery(hql).setParameter(0, account).setParameter(1, password).list();
}
User类添加List接收角色列表(说好的不能改呢?其实结构没变,就加字段而已~by鲁迅)
private List<UserRole> userRoles;
然后就可以顺利的从User里获取对应的角色了~
2.登录+登陆过滤器
登录
写烂了的方法…账号密码查询,然后上传Session
userService.findUserByAccountAndPass(user.getAccount(),user.getPassword());
判断是否null后上传Session方便前台调用数据和以后过滤
//把常用字符串保存到常量类里方便使用:Constant.USER
ServletActionContext.getRequest().getSession().setAttribute(Constant.USER, list.get(0));
log4j添加日志
Log log = LogFactory.getLog(getClass());
log.info("用户名为:"+list.get(0).getName()+"的用户登陆了系统。");
登录过滤器
过滤器基础:继承Filter类+在doFilter里写过滤方法体
public class LoginFilter implements Filter {
public void destroy() {
// TODO Auto-generated method stub
}
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
throws IOException, ServletException {
// TODO Auto-generated method stub
web.xml配置:注意配置顺序(要放在struts拦截器之前)
class:全类名
url-pattern:拦截url的表达式类型
<filter>
<filter-name>loginFilter</filter-name>
<filter-class>com.vincent.core.filter.LoginFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>loginFilter</filter-name>
<url-pattern>*.action</url-pattern>
</filter-mapping>
解决任何人可以通过修改url访问任何的漏洞:判断Session是否存在User类
注意要绕过登录,否则会在登录Action执行时判断不可能存在的User,导致永远无法登录- -
String uri = request.getRequestURI();
//判断uri是否是登录请求,是就放行,否则进行下一级过滤
if(!uri.contains("/sys/login_")){
//判断Session中是否存在User来查看是否已登录
if(request.getSession().getAttribute(Constant.USER)!=null){
解决没有角色权限的用户可以访问权限页面的漏洞:用Session中的User类获取角色判断字段
//判断uri中是否为子模块请求
if(uri.contains("/ssh/")){
User user = (User) request.getSession().getAttribute(Constant.USER);
//让其他工具类执行角色权限审核
PermissionCheck pc = new PermissionCheckImpl();
if(pc.isAccessable(user, "nsfw")){
工具类内部代码+测试单方多对多级联映射
public boolean isAccessable(User user, String privilege) {
// TODO Auto-generated method stub
List<UserRole> list = user.getUserRoles();
if(list!=null&&list.size()>0){
for(UserRole ur:list){
for(RolePrivilege rp:ur.getId().getRole().getRolePrivilges()){
if(privilege.equals(rp.getId().getCode())){
return true;
}
}
}
}
return false;
}
3.琐碎
s:checkBox标签遍历List
自动遍历栈顶list自动装入checkBox里
要指定listKey(标签的value)和listValue(标签显示出来的内容)
<s:checkboxlist
list="#roleList"
name="userRoleIds"
listKey="roleId"
listValue="name"></s:checkboxlist>
s:checkBox标签遍历Map
只需要指定栈内的Map即可自动装入
<s:checkboxlist list="#privilegeMap" name="privilegesIds"></s:checkboxlist>
编辑要显示角色类要在跳转action中把角色类压入栈
ActionContext.getContext().put("roleList", roleService.findAll());
更新用户角色要先清空用户原有角色字段(逻辑问题)
public void updateUserAndRole(User user, String... userRoleIds) {
// TODO Auto-generated method stub
userDao.cleanUserRoleById(user.getId());
update(user);
if(userRoleIds!=null){
for(String roleId:userRoleIds){
userDao.saveUserRole(new UserRole(new UserRoleId(new Role(roleId),user.getId())));
}
}
}