经过两天的编写,页面和控制器全部编写完毕,由于只是拿过来修改,所以具体代码就不放了,而且比原来简单好多。我们来看一下新的安全设置
目前为止有三个角色,ADMIN
,SUPERUSER
和USER
。其中ADMIN
可以调整其他角色的权限。SUPERUSER
可以进行删除操作,USER
则只能进行录入和修改。为了方便起见,还可以添加第四种角色,即访客GUEST
,访客只能进入各种列表和详情页查看,无法进行增删改。
设置第四个角色-访客
访客的角色名定义为GUEST
,由于借助了Spring Security
框架,所以新角色的扩展非常方便。
在初始SQL
文件中写入第四个角色
在dataInitialize.sql
最开始写入角色的部分加上如下内容:
INSERT INTO role(id, role)
VALUES (4, 'GUEST')
ON CONFLICT (role) DO NOTHING;
重新运行之后,就向ROLE
表中写入了第四种角色
修改用户编辑页面
既然有了第四种角色,就要在修改用户权限的界面里加上这一个角色。找到src/main/resources/templates/admin/userEdit.html
,在其中的修改用户权限部分,下边加入如下代码:
<div class="form-check form-check-inline">
<input class="form-check-input" type="radio" name="role" id="guest" value="GUEST"
th:checked="${user.hasRole('GUEST')}">
<label class="form-check-label" for="guest">访客用户</label>
</div>
注意其实用户是可以有多个角色的,这里我并没有像重构过程中把合同类别与合同的关系从多对多改成一对多。不过我在代码上依然使用用户和角色一对一的方式,也许哪天系统复杂了,再来多对多吧。
至于其他代码,由于都写好了对应关系,因此无需修改。
配置SecurityConfig
类
这里先来看一下当前的配置:
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/").permitAll()
.antMatchers("/initial/**").permitAll()
.antMatchers("/css/**", "/img/**", "/js/**", "/webfonts/**", "/test").permitAll()
.antMatchers("/account/register").permitAll()
.antMatchers("/account/reset").permitAll()
.antMatchers("/account/reset/**").permitAll()
.antMatchers("/admin/**").hasAuthority("ADMIN")
.antMatchers("/account/login**").permitAll()
.antMatchers("/pms/project/delete").hasAnyAuthority("ADMIN", "SUPERUSER")
.antMatchers("/pms/subject/delete").hasAnyAuthority("ADMIN", "SUPERUSER")
.antMatchers("/pms/contract/delete").hasAnyAuthority("ADMIN", "SUPERUSER")
.antMatchers("/pms/journal/delete").hasAnyAuthority("ADMIN", "SUPERUSER")
.anyRequest().authenticated()
.and()
.formLogin().loginPage("/account/login").loginProcessingUrl("/account/auth").permitAll()
.and()
.logout().logoutUrl("/account/signout").logoutSuccessUrl("/").permitAll()
.and().sessionManagement().maximumSessions(1).sessionRegistry(sessionRegistry);
}
可以看到,目前允许ADMIN
和SUPERUSER
来访问可删除的路径,很显然,为了阻止访客访问添加和修改路径,只需要再加几行配置即可:
.antMatchers("/pms/project/add").hasAnyAuthority("ADMIN", "SUPERUSER","USER")
.antMatchers("/pms/project/edit/**").hasAnyAuthority("ADMIN", "SUPERUSER","USER")
.antMatchers("/pms/subject/**/add").hasAnyAuthority("ADMIN", "SUPERUSER","USER")
.antMatchers("/pms/subject/edit/**").hasAnyAuthority("ADMIN", "SUPERUSER","USER")
.antMatchers("/pms/contract/**/add").hasAnyAuthority("ADMIN", "SUPERUSER","USER")
.antMatchers("/pms/contract/edit/**").hasAnyAuthority("ADMIN", "SUPERUSER","USER")
.antMatchers("/pms/journal/**/add").hasAnyAuthority("ADMIN", "SUPERUSER","USER")
.antMatchers("/pms/journal/edit/**").hasAnyAuthority("ADMIN", "SUPERUSER","USER")
这样就可以阻止访客对于所有新增和修改链接的访问了。有了访客之后,让其他人进入系统就变得相当方便了,只要给开一个访客权限,可以放心让其查看所有相关内容,但不能增删改。
搜索功能
原来的搜索功能被我暂时删除了,只保留了几个Dao
中的搜索方法。这次主要还是使用URL
传参的方法,然后改进一下搜索页面的展示效果。
我们现在有了项目-合同类别-合同-明细记录四个字段,如果要模糊搜索的话,要从以下字段中进行搜索:
- 项目-项目名称
- 项目-项目描述
- 合同类型-名称
- 合同-合同名称
- 合同-合同编号
- 合同-主要合同方
- 合同-次要供应商1
- 合同-次要供应商2
- 合同-次要供应商3
- 明细记录-说明
根据上述设计,先来把各个Dao
中的搜索方法重写一下。
Dao
与业务层编写
搜索方法上次写过一次了,采用findAll+
字段+Containing+Or
的格式,搜几个字段就要给几个字符串参数。
ProjectDao
搜索两个字段:
public interface ProjectDao extends JpaRepository<Project, Integer> {
Set<Project> findAllByProjectNameContainingOrProjectDescriptionContaining(String target1, String target2);
}
SubjectDao
只需要搜索类别名称:
public interface SubjectDao extends JpaRepository<Subject, Integer> {
Set<Subject> findAllBySubjectNameContaining(String target);
}
ContractDao
合同类中就比较多一些,长达6个字段的搜索,但也只是长,不难:
public interface ContractDao extends JpaRepository<Contract, Integer> {
Set<Contract> findAllByNameContainingOrNumberContainingOrSupplierContainingOrSecondarySupplier1ContainingOrSecondarySupplier2ContainingOrSecondarySupplier3Containing(
String t1, String t2, String t3, String t4, String t5, String t6);
}
JournalDao
只需要搜索说明:
public interface JournalDao extends JpaRepository<Journal, Integer> {
// 搜索方法
Set<Journal> findAllByDescriptionContaining(String target);
}
业务层的修改
这里我要把方法名称都统一掉,在每个业务层中,搜索方法都叫做search
,如下:
// Project中的搜索方法
@Transactional
public Set<Project> search(String target) {
return projectDao.findAllByProjectNameContainingOrProjectDescriptionContaining(target,target);
}
// Subject 搜索方法
@Transactional
public Set<Subject> search(String target) {
return subjectDao.findAllBySubjectNameContaining(target);
}
// Contract 搜索功能
@Transactional
public Set<Contract> search(String target) {
return contractDao.findAllByNameContainingOrNumberContainingOrSupplierContainingOrSecondarySupplier1ContainingOrSecondarySupplier2ContainingOrSecondarySupplier3Containing(
target, target, target, target, target, target
);
}
// Journal 搜索功能
@Transactional
public Set<Journal> search(String target) {
return journalDao.findAllByDescriptionContaining(target);
}
页面我现在还是沿用原来的设计,暂时没有想到什么更好的展示方法,反正也足够使用了。目前就先这样,下周可以正式开始使用了。
下边要添加的功能就是以excel的形式导出项目台账了,这个需要研究一下Java
操作Excel
的包。未来如果填表的自动化程度比较好,还可以开发填表的功能。