当前位置:网站首页>ssm练习第四天_获取用户名_用户退出_用户crud_密码加密_角色_权限
ssm练习第四天_获取用户名_用户退出_用户crud_密码加密_角色_权限
2022-07-26 17:31:00 【奇迹是执着的人创造的】
一、第一章:用户认证功能完善
第一节:显示用户名功能
使用SpringSecurity框架进行操作时,SpringSecurity会产生一个上下文对象SecurityContext,该上下文对象会被自动存储到session域中,于此同时也会将该上下文对象绑定到当前线程上,通过SecurityContext可以获得认证对象Authentication,而认证对象Authentication内部封装了principal(主角)属性,该principal就是当前用户对象User,而User对象自然包含用户名等信息。
获取过程:SecurityContext—>Authentication—>User—>username
1、获得用户名方式一:
服务器端可以通过程序API的方式获得
@RequestMapping("/showUsername")
public void showUsername(HttpServletRequest request){
//获取session对象
HttpSession session = request.getSession();
//从session域中获取username [框架帮你放的session key是多少呢?]
//方法是人想的 先获取所有属性名试试
Enumeration attributeNames = session.getAttributeNames();
//遍历枚举类型 和遍历结果集一样
while(attributeNames.hasMoreElements()){
System.out.println(attributeNames.nextElement());
}
//只有一个:SPRING_SECURITY_CONTEXT
// 顾名思义 安全框架的上下文对象 不是简单的一个个键值对 而是封装了一个类对象放到session中
//System.out.println(session.getAttribute("SPRING_SECURITY_CONTEXT"));
SecurityContext securityContext = (SecurityContext) session.getAttribute("SPRING_SECURITY_CONTEXT");
//从上下文对象中获取认证信息
Authentication authentication = securityContext.getAuthentication();
//Principal:首要的 (就是用户对象)--用户详情(UserDetails)
Object principal = authentication.getPrincipal();
User user= (User) principal;
//获取用户名
String username = user.getUsername();
System.out.println(username);
//方法二 如此重要的context不可能让你每次到session中拿 怎么也得提供个静态方法来获取吧 果不其然
SecurityContext context = SecurityContextHolder.getContext();
System.out.println(context==securityContext);//获得的是同一个对象 地址都一样啊(上下文对象也只可能有一个)
User user1= (User) context.getAuthentication().getPrincipal();
System.out.println(user1.getUsername());
}
简单获取方法就是:
SecurityContext context = SecurityContextHolder.getContext();
User user= (User) context.getAuthentication().getPrincipal();
System.out.println(user.getUsername());
2、获得用户名方式二:
在页面中通过el表达式从session域中获得 el表达式
根据demo session中获取username的方法 不难理解这种前端获取username的写法
${sessionScope.SPRING_SECURITY_CONTEXT.authentication.principal.username}
3、获得用户名方式三:
在页面中通过SpringSecurity的标签直接获得
spring_SECURITY提供的一套标签库
既然是标签库肯定腰线引入:
<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>
<security:authentication property="principal.username" />
4、显示用户名效果

第二节:用户退出功能
在header.jsp的页面中编写超链接
就是路径写成/logout绝对路径即可 logout和/login一样 xml里配置的路径
<a href="${pageContext.request.contextPath}/logout"
class="btn btn-default btn-flat">注销</a>
注意必须写绝对路径
配置时麻烦用起来太简单了
第二章:用户模块
第一节:用户列表查询功能
1、页面入口

2、编写Controller
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
UserService userService;
@RequestMapping("/findAll")
public ModelAndView findAll(){
List<SysUser> users = userService.findAll();
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("users",users);
modelAndView.setViewName("user-list");
return modelAndView;
}
}
3、编写Service
接口
public interface UserService extends UserDetailsService{
/** * 查询全部 * @return */
List<SysUser> findAll();
}
实现
@Override
public List<SysUser> findAll() {
return userdao.findAll();
}
4、编写Dao
@Select("select * from sys_user")
List<SysUser> findAll();
第二节:添加用户功能
1、页面入口

写安全框架时表和javaBean都有了
2、编写Controller
@RequestMapping("/save")
public String save(SysUser user){
userService.save(user);
return "redirect:/user/findAll";
}
3、编写Service
接口
void save(SysUser user);
实现
@Override
public void save(SysUser user) {
//user.setPassword(MD5Utils.md5(user.getPassword()));//md5加密穷举法可破解
userdao.save(user);
}
4、编写Dao
@Insert("insert into sys_user values(user_seq.nextval,#{username},#{email},#{password},#{phoneNum},#{status})")
void save(SysUser user);
第三节:判断唯一用户名
1、页面入口

编写页面
<script type="text/javascript">
function isUniqueUsername(a) {
//alert(a.value);//也能得到a 表示整个input框 dom元素类型
//alert($("#username").val());//jquery方式肯定也能得到
var username=$("#username").val();
//请求controller,判断用户名是否唯一
//不能刷新整个页面 因此必须ajax异步请求
$.ajax({
url:"${pageContext.request.contextPath}/user/isUniqueUsername",
//data:"username="+username,//后端能收到
data:{
"username":username},//后端也能收到
success:function (data) {
//alert(data);
if(data == "false"){
//返回的是false字符串啊 转json流返回的
//提示用户名已经被占用 -- 设置文本框为红色,宽度为1,样式为实线
$("#username").attr("style","border:red 2px solid");//.css用不了 因为已经有个class样式了
//保存按钮设置为不可用
$("#saveBtn").prop("disabled","disabled");
//attr("disabled","true");//然后下面写false也行
}else{
//取消样式
$("#username").removeAttr("style");
$("#username").addClass("form-control")//如果样式没有了 需要加上原来的样式
//保存按钮设置为可用
$("#saveBtn").removeAttr("disabled");
}
},
//dataType:"text",//一般可以省略
type:"GET"
});
}
</script>
注:pl/sql development 修改式查询
select * from sys_user for update;

2、编写Controller
springMVC返回值就3种 void string modelAndView 没有bool等其他类型 只能三选一
@ResponseBody:把结果集转成json以流的形式返回(否则会进入视图解析器跳转404页面)
//springMVC返回值就3种 void string modelAndView 没有bool等其他类型 只能三选一
//@ResponseBody:把结果集转成json以流的形式返回(否则会进入视图解析器跳转404页面)
@RequestMapping("/isUniqueUsername")
@ResponseBody
public String isUniqueUsername(String username){
LogUtils.print(username);
Boolean b=userService.isUniqueUsername(username);
return ""+b;//转字符串返回
}
3、编写service
接口:
Boolean isUniqueUsername(String username);
实现:
@Override
public Boolean isUniqueUsername(String username) {
SysUser user = userdao.findAllUserByUsername(username);
return user == null;
}
4、编写Dao
注意前面的findByUsername方法需要加个条件: 关闭的用户不允许登录
此处不管状态问题,都要判重,因此不能沿用之前的方法了
/** * 根据用户名查询单个用户 不忽略关闭状态的用户 * @param username * @return */
@Select("select * from sys_user where username=#{abc}")
SysUser findAllUserByUsername(String username);
第四节:用户密码的加密操作
为了客户账户的安全性,在数据库中不能明文显示密码,所以就需要对客户端提交的密码进行加密后在存储到数据库中。原来可以使用md5、加盐加密等工具进行密码加密,目前我们使用的SpringSecurity框架本身就提供了加密工具。
0、md5加密
可以暴力破解 不大好
@Override
public void save(SysUser user) {
//获取明文密码
String password = user.getPassword();
//对明文密码进行加密
String md5Password = MD5Utils.md5(password);
//把加密后的密码存储到user对象中
user.setPassword(md5Password);
userDao.save(user);
}
1、在spring-security.xml中配置加密类BCryptPasswordEncoder
<!--创建加密工具类对象-->
<bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"></bean>
2、修改save业务方法
@Autowired
PasswordEncoder passwordEncoder;//上面xml中已经创建了 容器中已经有了
@Override
public void save(SysUser user) {
//user.setPassword(MD5Utils.md5(user.getPassword()));//md5无法防止暴力破解
user.setPassword(passwordEncoder.encode(user.getPassword()));//安全框架的加密很牛
userdao.save(user);
}
3、加密效果

4、修改登录操作
<!-- 配置认证信息 -->
<security:authentication-manager>
<!--认证信息的提供者: 关联用户服务对象 - 提供账号和密码-->
<security:authentication-provider user-service-ref="userServiceImpl"><!--使用的是ioc容器内的默认名称-->
<!--登录时要加密密码:指定登录加密工具类-->
<security:password-encoder ref="passwordEncoder"></security:password-encoder>
</security:authentication-provider>
</security:authentication-manager>
<!--创建加密工具类对象 在下面时 此配置第1步就添加了-->
<bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"></bean>

修改userServiceImpl的认证方法loadUserByUsername
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
//System.out.println(username);
SysUser sysUser = userdao.findByUsername(username);
if(sysUser==null) return null;
//配置文件里没有指定角色了 需要自己创建角色对象
//创建角色的集合对象
Collection<GrantedAuthority> authorities=new ArrayList<>();
//创建临时角色对象 正常情况下应该是数据库角色表中查的
GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("ROLE_USER");
//对象添加到集合中
authorities.add(grantedAuthority);
//User是安全框架内实现了UserDetails接口的一个类
//第三个参数是:角色列表对象 (此处角色名ROLE_USER自己定义 xml里需要这个名字)
//{noop}前缀表示不加密 该把不加密去掉了
UserDetails user = new User(sysUser.getUsername(),sysUser.getPassword(),authorities);
return user;
}

注:放在下面比较好
第三章:角色模块
第一节:角色表与实体的创建
1、角色表建表语句和字段含义
create sequence role_seq;
CREATE TABLE sys_role(
id number PRIMARY KEY,
roleName VARCHAR2(50) ,
roleDesc VARCHAR2(50)
)
insert into sys_role values(role_seq.nextval, 'ADMIN','管理员');
select * from sys_role;
字段含义:
| 序号 | 字段名称 | 字段类型 | 字段描述 |
|---|---|---|---|
| 1 | id | bigint | 无意义,主键自动增长 |
| 2 | roleName | varchar | 角色名 |
| 3 | roleDesc | varchar | 角色描述 |
2、Role实体创建
@Data
public class Role {
private Integer id;
private String roleName;
private String roleDesc;
}
第二节:角色列表查询功能
1、页面入口

2、编写Controller
@Controller
@RequestMapping("/role")
public class RoleController {
@Autowired
RoleService roleService;
@RequestMapping("/findAll")
public ModelAndView findAll(){
List<Role> roles = roleService.findAll();
LogUtils.print(roles);
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("roles",roles);
modelAndView.setViewName("role-list");
return modelAndView;
}
}
3、编写Service
接口
List<Role> findAll();
实现
@Override
public List<Role> findAll() {
return roleDao.findAll();
}
4、编写Dao
@Select("select * from sys_role")
List<Role> findAll();
第三节:添加角色功能
1、页面入口

2、编写Controller
@RequestMapping("/save")
public String save(Role role){
LogUtils.print(role);
roleService.save(role);
return "redirect:findAll";
}
3、编写Service
接口
void save(Role role);
实现
@Override
public void save(Role role) {
roleDao.save(role);
}
4、编写Dao
@Insert("insert into sys_role values(role_seq.nextval,#{roleName},#{roleDesc})")
void save(Role role);
第四章:权限模块
第一节:权限表与实体的创建
1、权限表建表语句和字段含义
-- 权限管理
create sequence permission_seq;
-- pid关联自己表id 称为上级权限id 没有上级的pid为0
CREATE TABLE sys_permission(
id number PRIMARY KEY,
permissionName VARCHAR2(50) ,
url VARCHAR2(50),
pid number
)
select * from sys_permission for update;
select permission_seq.nextval from dual;
select * from sys_permission;
手动添加数据:
然后将序列刷到5 防止下次插入总是主键冲突
select permission_seq.nextval from dual;

字段含义:
| 序号 | 字段名称 | 字段类型 | 字段描述 |
|---|---|---|---|
| 1 | id | bigint | 无意义 |
| 2 | permissionName | varchar | 权限名 |
| 3 | url | varchar | 资源路径 |
| 4 | pid | bigint | 父菜单id |
注: 设置pl/sql development 执行sql自动提交事务

2、Permission实体创建
@Data
public class Permission {
private Integer id;
private String permissionName;
private String url;
private Integer pid;//写简单的pid 不能写Permission对象 随便想想也是死循环
}
第二节:权限列表查询功能
1、页面入口

2、编写Controller
@RequestMapping("/findAll")
public ModelAndView findAll(){
List<Permission> permissions= permissionService.findAll();
LogUtils.print(permissions);
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("permissions",permissions);
modelAndView.setViewName("permission-list");
return modelAndView;
}
3、编写Service
接口
List<Permission> findAll();
实现
@Override
public List<Permission> findAll() {
return permissionDao.findAll();
}
4、编写Dao
@Select("select * from sys_permission")
List<Permission> findAll();
前端没怎么改 简单的c:foreach循环
第三节:添加权限功能-回显父菜单
1、页面入口

<div class="col-md-2 title">父权限</div>
<div class="col-md-4 data">
<select class="form-control select2" style="width: 100%"
name="pid">
<c:forEach items="${permissions}" var="p">
<option value="${p.id}" selected="selected">${
p.permissionName}</option>
</c:forEach>
</select>
</div>
2、编写Controller
/** * 添加数据回显 * 主要就是数据库中查询所有父权限 然后在下拉选中显示出来 */
@RequestMapping("/saveUI")
public ModelAndView saveUI(){
List<Permission> permissions=permissionService.findAllParentPermission();
LogUtils.print(permissions);
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("permissions",permissions);
modelAndView.setViewName("permission-add");
return modelAndView;
}
3、编写Service
接口
/** * 查询所有父权限 * @return */
List<Permission> findAllParentPermission();
实现
@Override
public List<Permission> findAllParentPermission() {
return permissionDao.findAllParentPermission();
}
4、编写Dao
/** * 查询所有父权限 * @return */
@Select("select * from sys_permission where pid=0")
List<Permission> findAllParentPermission();
第四节:添加权限功能-保存到数据库
1、页面入口

2、编写Controller
@RequestMapping("/save")
public String save(Permission permission){
LogUtils.print(permission);
permissionService.save(permission);
return "redirect:/permission/findAll";
}
3、编写Service
接口
void save(Permission permission);
实现
@Override
public void save(Permission permission) {
permissionDao.save(permission);
}
4、编写Dao
/** * 保存权限 * @param permission */
@Select("insert into sys_permission values(permission_seq.nextval,#{permissionName},#{url},#{pid})")
void save(Permission permission);
翻博客 查看statueStr的含义
边栏推荐
- openssl
- PMP Exam details, what changes have been made to the new exam outline?
- 跟我学 UML 系统建模
- 【集训Day2】cinema ticket
- DTS is equipped with a new self-developed kernel, which breaks through the key technology of the three center architecture of the two places Tencent cloud database
- 老子云携手福昕鲲鹏,首次实现3D OFD三维版式文档的重大突破
- 3、 Topic communication: create your own information format
- [template] segment tree 1
- web项目文件简单上传和下载
- 10、 Implementation of parameter modification of parameter server
猜你喜欢
随机推荐
[Digital IC] understand Axi Lite protocol in simple terms
CentOS installs docker and MySQL and redis environments
SQL判断某列中是否包含中文字符、英文字符、纯数字,数据截取
AI sky covering DL multilayer perceptron
【英雄哥七月集训】第 25天: 树状数组
中国聚异丁烯市场研究与投资价值报告(2022版)
效率提升98%!高海拔光伏电站运维巡检背后的AI利器
Several ways to resolve hash conflicts
“蔚来杯“2022牛客暑期多校训练营3记录
有一说一,阿里P7的薪资待遇是真的香
Cross Site Request Forgery (CSRF)
SSH based online mall
Relative path and absolute path
Common APIs
8.1 Diffie-Hellman密钥交换
[day3] reconstruction of roads
Spark数据格式UnsafeRow
[training Day1] Dwaves line up
Simple uploading and downloading of Web project files
Hosts this file has been set to read-only solution







![[unity3d] rocker](/img/b7/40643a2676b251c185ce58840f7581.png)

