03SSM综合案例之16SpringSecurity(一)https://developer.aliyun.com/article/1432883
四、 用户登录问题分析
问题一:登录失败的问题
在数据库中是有jack这个用户的
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-f9gasAmT-1666446103178)(assets/image-20201015170433128.png)]
为什么还是没办法登录,原因是在于我们的spring-security.xml配置文件中配置的问题:
在配置文件中,我们配置了
<!-- 配置具体的拦截的规则 pattern="请求路径的规则" access="访问系统的人,必须有ROLE_USER的角色" --> <security:intercept-url pattern="/**" access="ROLE_USER,ROLE_ADMIN"/>
spring security 拦截了所有的请求,要想登录认证必须是有ROLE_USER,ROLE_ADMIN
两个权限的,在UserServiceImpl类中我将查询到的UserInfo
中的信息封装到了User
对象中,有一个值是为null
User user = new User(userInfo.getUsername(),userInfo.getPassword(), null);
也就是说我们查询出的这个对象是没有权限的,既是用户名和密码对了,没有权限也是没有办法登录的!
在这里我们需要模拟给出ROLE_USER,ROLE_ADMIN
两个权限,修改UserServiceImpl类
@Service("userService") public class UserServiceImpl implements UserService { @Autowired UserMapper userMapper; @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { //查询数据返回实体类对应数据 Users users = userMapper.selectByUserName(username); if(users!=null){ //创建springSecurity主体中存储的账号对象并返回(账号,密码,权限列表) UserDetails userDetails=new User(users.getUsername(),users.getPassword(),getAuthority()); return userDetails; } return null; } public List<SimpleGrantedAuthority> getAuthority(){ ArrayList<SimpleGrantedAuthority> simpleGrantedAuthorities = new ArrayList<>(); simpleGrantedAuthorities.add(new SimpleGrantedAuthority("ROLE_USER")); simpleGrantedAuthorities.add(new SimpleGrantedAuthority("ROLE_ADMIN")); return simpleGrantedAuthorities; } }
修改完毕之后我们再次测试,看是否能登录成功!
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EBq1kGou-1666446103180)(assets/image-20201015172905442.png)]
这个报错的原因是spring security 默认使用的是密文提交的,现在没有进行加密! 我们只需要在获取密码的前面加上"{noop}" 代表的是使用明文
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZFX4KXjq-1666446103180)(assets/image-20201015205108314.png)]
此时就认证成功
问题二:数据库查询用户角色
在上面的代码中我们的用户角色是自己手动添加的,这不是通用的一种方式,用户的角色我们要从数据库中进行查询!
修改UserMapper.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="cn.yanqi.ssm.mapper.UserMapper"> <!--通过用户名查询用户--> <resultMap id="userResultMap" type="UserInfo" autoMapping="true"> <id property="id" column="id" /> <collection property="roles" ofType="Role" javaType="List" autoMapping="true"> <id property="id" column="rid" /> </collection> </resultMap> <select id="findUserByUserName" resultMap="userResultMap"> SELECT * , r.id rid FROM users u, role r, users_role ur WHERE u.id = ur.userId AND r.id = ur.roleId AND u.username = #{username} </select> </mapper>
修改UserService
在这里需要注意的是,获取到对应的角色之后,其实还是不能登录,在users表中,有一个字段status
,这个字段表示的用户是否可能,0表示可用 1表示不可用。此时的功能原来使用的构造已经无法满足了,我们需要使用另外一个构造
public User(String username, String password, /** boolean enabled: 账户是否可用 boolean accountNonExpired:账户是否过期 boolean credentialsNonExpired:密码是否过期 boolean accountNonLocked:账户是否冻结被锁定 authorities:该账户所具有的权限 */ boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) { }
完整代码实现
@Service("userService") public class UserServiceImpl implements UserService { @Autowired private UserMapper userMapper; @Override public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException { UserInfo userInfo = userMapper.findUserByUserName(s); User user = new User(userInfo.getUsername(), "{noop}"+userInfo.getPassword(), userInfo.getStatus() == 0 ? false : true , true,true,true, getAuthority(userInfo.getRoles())); return user; } public List<SimpleGrantedAuthority> getAuthority(List<Role> roles){ ArrayList<SimpleGrantedAuthority> simpleGrantedAuthorities = new ArrayList<>(); for (Role role : roles) { simpleGrantedAuthorities.add(new SimpleGrantedAuthority("ROLE_"+role.getRoleName())); } return simpleGrantedAuthorities; } }
五、权限管理
5.1 查询权限
编写PermissionMapper接口
public interface PermissionMapper { //查询所有权限数据 @Select("select * from permission") public List<Permission> selectAll(); }
编写PermissionService
public interface PermissionService { //查询所有权限数据 public List<Permission> findAll(); }
@Service("permissionService") public class PermissionServiceImpl implements PermissionService { @Autowired PermissionMapper permissionMapper; @Override public List<Permission> findAll() { return permissionMapper.selectAll(); } }
编写PermissionController
@Controller @RequestMapping("/permission") public class PermissionController { @Autowired PermissionService permissionService; //查询所有数据 @RequestMapping("/findAll") public String findAll(HttpServletRequest request, @RequestParam(value = "page",required = false,defaultValue = "1") int page, @RequestParam(value = "limit",required = false,defaultValue = "5")int limit){ PageHelper.startPage(page,limit); List<Permission> all = permissionService.findAll(); PageInfo<Permission> pageInfo=new PageInfo<>(all); request.setAttribute("pageInfo",pageInfo); return "/permission/permission-list"; } }
测试
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hq3GBsyg-1666446103181)(assets/image-20220525145959457.png)]
5.2 添加权限
编写PermissionMapper接口
// 添加权限数据 @Insert("insert into permission (permissionName,url) values(#{permissionName},#{url})") public int insert(Permission permission);
编写PermissionService
//添加权限数据 public int add(Permission permission);
/** * 添加资源权限 * @param permission */ @Override public int add(Permission permission) { return permissionMapper.insert(permission); }
编写PermissionController
@Controller @RequestMapping("permission") public class PermissionController { @Autowired private PermissionService permissionService; /** * 添加资源权限 * @param permission * @return * @throws Exception */ @RequestMapping(value = "/add",method = RequestMethod.POST) public String add(HttpServletRequest request,Permission permission){ permissionService.add(permission); return "redirect:/permission/findAll"; } }
测试
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MjJtEe1l-1666446103182)(assets/image-20220525145939176.png)]
5.3 删除权限
独立完成,注意删除域角色关联表对应的资源权限信息
编写PermissionMapper接口
// 根据id删除权限数据 @Delete("delete from permission where id=#{id}") public int deleteById(int id);
编写PermissionService
//根据id删除权限数据 public int delete(int id);
/** * 删除资源权限 * @param id */ @Override public int delete(int id) { return permissionMapper.deleteById(id); }
编写PermissionController
@Controller @RequestMapping("permission") public class PermissionController { @Autowired private PermissionService permissionService; /** * 删除资源权限 * @param id * @return * @throws Exception */ @RequestMapping("/deleteById") public String deleteById(HttpServletRequest request,int id){ permissionService.delete(id); return "redirect:/permission/findAll"; } }
rmissionService.add(permission); return “redirect:/permission/findAll”; } }
### 测试 [外链图片转存中...(img-MjJtEe1l-1666446103182)] ## 5.3 删除权限 独立完成,注意删除域角色关联表对应的资源权限信息 ### 编写PermissionMapper接口 ```java // 根据id删除权限数据 @Delete("delete from permission where id=#{id}") public int deleteById(int id);
编写PermissionService
//根据id删除权限数据 public int delete(int id);
/** * 删除资源权限 * @param id */ @Override public int delete(int id) { return permissionMapper.deleteById(id); }
编写PermissionController
@Controller @RequestMapping("permission") public class PermissionController { @Autowired private PermissionService permissionService; /** * 删除资源权限 * @param id * @return * @throws Exception */ @RequestMapping("/deleteById") public String deleteById(HttpServletRequest request,int id){ permissionService.delete(id); return "redirect:/permission/findAll"; } }