SSH纳税服务项目重点细节归纳4

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())));
        }
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_42839338/article/details/81348460