diff --git a/src/main/java/com/boot/security/server/config/SecurityConfig.java b/src/main/java/com/boot/security/server/config/SecurityConfig.java index 6f13c79..68c3347 100644 --- a/src/main/java/com/boot/security/server/config/SecurityConfig.java +++ b/src/main/java/com/boot/security/server/config/SecurityConfig.java @@ -1,11 +1,12 @@ package com.boot.security.server.config; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.web.authentication.AuthenticationFailureHandler; import org.springframework.security.web.authentication.AuthenticationSuccessHandler; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; @@ -24,6 +25,11 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsServiceImpl userDetailsServiceImpl; + @Bean + public BCryptPasswordEncoder bCryptPasswordEncoder() { + return new BCryptPasswordEncoder(); + } + @Override protected void configure(HttpSecurity http) throws Exception { http.authorizeRequests() @@ -38,18 +44,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { - auth.userDetailsService(userDetailsServiceImpl).passwordEncoder(new PasswordEncoder() { - - @Override - public boolean matches(CharSequence rawPassword, String encodedPassword) { - return rawPassword.equals(encodedPassword); - } - - @Override - public String encode(CharSequence rawPassword) { - return rawPassword.toString(); - } - }); + auth.userDetailsService(userDetailsServiceImpl).passwordEncoder(bCryptPasswordEncoder()); } } diff --git a/src/main/java/com/boot/security/server/controller/PermissionController.java b/src/main/java/com/boot/security/server/controller/PermissionController.java new file mode 100644 index 0000000..12af238 --- /dev/null +++ b/src/main/java/com/boot/security/server/controller/PermissionController.java @@ -0,0 +1,189 @@ +package com.boot.security.server.controller; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.util.CollectionUtils; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.boot.security.server.dao.PermissionDao; +import com.boot.security.server.model.Permission; +import com.boot.security.server.model.SysUser; +import com.boot.security.server.service.PermissionService; +import com.google.common.collect.Lists; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * 权限相关接口 + * + * @author 小威老师 + * + */ +@Api(tags = "权限") +@RestController +@RequestMapping("/permissions") +public class PermissionController { + + @Autowired + private PermissionDao permissionDao; + @Autowired + private PermissionService permissionService; + + @ApiOperation(value = "当前登录用户拥有的权限") + @GetMapping("/current") + public List permissionsCurrent() {// TODO + List list = null; + if (list == null) { + list = new ArrayList<>(); + SysUser user = new SysUser(); + list = permissionDao.listByUserId(user.getId()); + } + final List permissions = list.stream().filter(l -> l.getType().equals(1)) + .collect(Collectors.toList()); + + setChild(permissions); + + return permissions.stream().filter(p -> p.getParentId().equals(0L)).collect(Collectors.toList()); + } + + private void setChild(List permissions) { + permissions.parallelStream().forEach(per -> { + List child = permissions.stream().filter(p -> p.getParentId().equals(per.getId())) + .collect(Collectors.toList()); + per.setChild(child); + }); + } + + /** + * 菜单列表 + * + * @param pId + * @param permissionsAll + * @param list + */ + private void setPermissionsList(Long pId, List permissionsAll, List list) { + for (Permission per : permissionsAll) { + if (per.getParentId().equals(pId)) { + list.add(per); + if (permissionsAll.stream().filter(p -> p.getParentId().equals(per.getId())).findAny() != null) { + setPermissionsList(per.getId(), permissionsAll, list); + } + } + } + } + + @GetMapping + @ApiOperation(value = "菜单列表") + public List permissionsList() { + List permissionsAll = permissionDao.listAll(); + + List list = Lists.newArrayList(); + setPermissionsList(0L, permissionsAll, list); + + return list; + } + + @GetMapping("/all") + @ApiOperation(value = "所有菜单") + public JSONArray permissionsAll() { + List permissionsAll = permissionDao.listAll(); + JSONArray array = new JSONArray(); + setPermissionsTree(0L, permissionsAll, array); + + return array; + } + + @GetMapping("/parents") + @ApiOperation(value = "一级菜单") + public List parentMenu() { + List parents = permissionDao.listParents(); + + return parents; + } + + /** + * 菜单树 + * + * @param pId + * @param permissionsAll + * @param array + */ + private void setPermissionsTree(Long pId, List permissionsAll, JSONArray array) { + for (Permission per : permissionsAll) { + if (per.getParentId().equals(pId)) { + String string = JSONObject.toJSONString(per); + JSONObject parent = (JSONObject) JSONObject.parse(string); + array.add(parent); + + if (permissionsAll.stream().filter(p -> p.getParentId().equals(per.getId())).findAny() != null) { + JSONArray child = new JSONArray(); + parent.put("child", child); + setPermissionsTree(per.getId(), permissionsAll, child); + } + } + } + } + + @GetMapping(params = "roleId") + @ApiOperation(value = "根据角色id删除权限") + public List listByRoleId(Long roleId) { + return permissionDao.listByRoleId(roleId); + } + + @PostMapping + @ApiOperation(value = "保存菜单") + public void save(@RequestBody Permission permission) { + permissionDao.save(permission); + } + + @GetMapping("/{id}") + @ApiOperation(value = "根据菜单id获取菜单") + public Permission get(@PathVariable Long id) { + return permissionDao.getById(id); + } + + @PutMapping + @ApiOperation(value = "修改菜单") + public void update(@RequestBody Permission permission) { + permissionDao.update(permission); + } + + /** + * 校验权限 + * + * @return + */ + @GetMapping("/owns") + @ApiOperation(value = "校验当前用户的权限") + public Set ownsPermission() {// TODO + List permissions = new ArrayList<>(); + if (CollectionUtils.isEmpty(permissions)) { + return Collections.emptySet(); + } + + return permissions.parallelStream().filter(p -> !StringUtils.isEmpty(p.getPermission())) + .map(Permission::getPermission).collect(Collectors.toSet()); + } + + @DeleteMapping("/{id}") + @ApiOperation(value = "删除菜单") + public void delete(@PathVariable Long id) { + permissionService.delete(id); + } +} diff --git a/src/main/java/com/boot/security/server/controller/RoleController.java b/src/main/java/com/boot/security/server/controller/RoleController.java new file mode 100644 index 0000000..eef22bc --- /dev/null +++ b/src/main/java/com/boot/security/server/controller/RoleController.java @@ -0,0 +1,92 @@ +package com.boot.security.server.controller; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.boot.security.server.dao.RoleDao; +import com.boot.security.server.dto.RoleDto; +import com.boot.security.server.model.Role; +import com.boot.security.server.page.table.PageTableHandler; +import com.boot.security.server.page.table.PageTableHandler.CountHandler; +import com.boot.security.server.page.table.PageTableHandler.ListHandler; +import com.boot.security.server.page.table.PageTableRequest; +import com.boot.security.server.page.table.PageTableResponse; +import com.boot.security.server.service.RoleService; +import com.google.common.collect.Maps; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +/** + * 角色相关接口 + * + * @author 小威老师 + * + */ +@Api(tags = "角色") +@RestController +@RequestMapping("/roles") +public class RoleController { + + @Autowired + private RoleService roleService; + @Autowired + private RoleDao roleDao; + + @PostMapping + @ApiOperation(value = "保存角色") + public void saveRole(@RequestBody RoleDto roleDto) { + roleService.saveRole(roleDto); + } + + @GetMapping + @ApiOperation(value = "角色列表") + public PageTableResponse listRoles(PageTableRequest request) { + return PageTableHandler. builder().countHandler(new CountHandler() { + + @Override + public int count(PageTableRequest request) { + return roleDao.count(request.getParams()); + } + }).listHandler(new ListHandler() { + + @Override + public List list(PageTableRequest request) { + List list = roleDao.list(request.getParams(), request.getOffset(), request.getLimit()); + return list; + } + }).build().handle(request); + } + + @GetMapping("/{id}") + @ApiOperation(value = "根据id获取角色") + public Role get(@PathVariable Long id) { + return roleDao.getById(id); + } + + @GetMapping("/all") + @ApiOperation(value = "所有角色") + public List roles() { + return roleDao.list(Maps.newHashMap(), null, null); + } + + @GetMapping(params = "userId") + @ApiOperation(value = "根据用户id获取拥有的角色") + public List roles(Long userId) { + return roleDao.listByUserId(userId); + } + + @DeleteMapping("/{id}") + @ApiOperation(value = "删除角色") + public void delete(@PathVariable Long id) { + roleService.deleteRole(id); + } +} diff --git a/src/main/java/com/boot/security/server/controller/UserController.java b/src/main/java/com/boot/security/server/controller/UserController.java new file mode 100644 index 0000000..e263303 --- /dev/null +++ b/src/main/java/com/boot/security/server/controller/UserController.java @@ -0,0 +1,114 @@ +package com.boot.security.server.controller; + +import java.util.List; + +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.boot.security.server.dao.UserDao; +import com.boot.security.server.dto.UserDto; +import com.boot.security.server.model.SysUser; +import com.boot.security.server.page.table.PageTableHandler; +import com.boot.security.server.page.table.PageTableHandler.CountHandler; +import com.boot.security.server.page.table.PageTableHandler.ListHandler; +import com.boot.security.server.page.table.PageTableRequest; +import com.boot.security.server.page.table.PageTableResponse; +import com.boot.security.server.service.UserService; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; + +/** + * 用户相关接口 + * + * @author 小威老师 + * + */ +@Api(tags = "用户") +@Slf4j(topic = "adminLogger") +@RestController +@RequestMapping("/users") +public class UserController { + + @Autowired + private UserService userService; + @Autowired + private UserDao userDao; + + @PostMapping + @ApiOperation(value = "保存用户") + public SysUser saveUser(@RequestBody UserDto userDto) { + SysUser u = userService.getUser(userDto.getUsername()); + if (u != null) { + throw new IllegalArgumentException(userDto.getUsername() + "已存在"); + } + + return userService.saveUser(userDto); + } + + @PutMapping + @ApiOperation(value = "修改用户") + public SysUser updateUser(@RequestBody UserDto userDto) { + return userService.updateUser(userDto); + } + + @PutMapping(params = "headImgUrl") + @ApiOperation(value = "修改头像") + public void updateHeadImgUrl(String headImgUrl) { +// SysUser user = UserUtil.getCurrentUser(); + SysUser user = new SysUser();// TODO + UserDto userDto = new UserDto(); + BeanUtils.copyProperties(user, userDto); + userDto.setHeadImgUrl(headImgUrl); + + userService.updateUser(userDto); + log.debug("{}修改了头像", user.getUsername()); + } + + @PutMapping("/{username}") + @ApiOperation(value = "修改密码") + public void changePassword(@PathVariable String username, String oldPassword, String newPassword) { + userService.changePassword(username, oldPassword, newPassword); + } + + @GetMapping + @ApiOperation(value = "用户列表") + public PageTableResponse listUsers(PageTableRequest request) { + return PageTableHandler. builder().countHandler(new CountHandler() { + + @Override + public int count(PageTableRequest request) { + return userDao.count(request.getParams()); + } + }).listHandler(new ListHandler() { + + @Override + public List list(PageTableRequest request) { + List list = userDao.list(request.getParams(), request.getOffset(), request.getLimit()); + return list; + } + }).build().handle(request); + } + + @ApiOperation(value = "当前登录用户") + @GetMapping("/current") + public SysUser currentUser() {// TODO +// User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + return new SysUser(); + } + + @ApiOperation(value = "根据用户id获取用户") + @GetMapping("/{id}") + public SysUser user(@PathVariable Long id) { + return userDao.getById(id); + } + +} diff --git a/src/main/java/com/boot/security/server/service/PermissionService.java b/src/main/java/com/boot/security/server/service/PermissionService.java new file mode 100644 index 0000000..d5bc1e3 --- /dev/null +++ b/src/main/java/com/boot/security/server/service/PermissionService.java @@ -0,0 +1,12 @@ +package com.boot.security.server.service; + +import com.boot.security.server.model.Permission; + +public interface PermissionService { + + void save(Permission permission); + + void update(Permission permission); + + void delete(Long id); +} diff --git a/src/main/java/com/boot/security/server/service/RoleService.java b/src/main/java/com/boot/security/server/service/RoleService.java new file mode 100644 index 0000000..f039c92 --- /dev/null +++ b/src/main/java/com/boot/security/server/service/RoleService.java @@ -0,0 +1,10 @@ +package com.boot.security.server.service; + +import com.boot.security.server.dto.RoleDto; + +public interface RoleService { + + void saveRole(RoleDto roleDto); + + void deleteRole(Long id); +} diff --git a/src/main/java/com/boot/security/server/service/UserService.java b/src/main/java/com/boot/security/server/service/UserService.java new file mode 100644 index 0000000..1528d92 --- /dev/null +++ b/src/main/java/com/boot/security/server/service/UserService.java @@ -0,0 +1,16 @@ +package com.boot.security.server.service; + +import com.boot.security.server.dto.UserDto; +import com.boot.security.server.model.SysUser; + +public interface UserService { + + SysUser saveUser(UserDto userDto); + + SysUser updateUser(UserDto userDto); + + SysUser getUser(String username); + + void changePassword(String username, String oldPassword, String newPassword); + +} diff --git a/src/main/java/com/boot/security/server/service/impl/PermissionServiceImpl.java b/src/main/java/com/boot/security/server/service/impl/PermissionServiceImpl.java new file mode 100644 index 0000000..0dfc78c --- /dev/null +++ b/src/main/java/com/boot/security/server/service/impl/PermissionServiceImpl.java @@ -0,0 +1,42 @@ +package com.boot.security.server.service.impl; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import com.boot.security.server.dao.PermissionDao; +import com.boot.security.server.model.Permission; +import com.boot.security.server.service.PermissionService; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j(topic = "adminLogger") +@Service +public class PermissionServiceImpl implements PermissionService { + + @Autowired + private PermissionDao permissionDao; + + @Override + public void save(Permission permission) { + permissionDao.save(permission); + + log.debug("新增菜单{}", permission.getName()); + } + + @Override + public void update(Permission permission) { + permissionDao.update(permission); + } + + @Override + @Transactional + public void delete(Long id) { + permissionDao.deleteRolePermission(id); + permissionDao.delete(id); + permissionDao.deleteByParentId(id); + + log.debug("删除菜单id:{}", id); + } + +} diff --git a/src/main/java/com/boot/security/server/service/impl/RoleServiceImpl.java b/src/main/java/com/boot/security/server/service/impl/RoleServiceImpl.java new file mode 100644 index 0000000..fe792be --- /dev/null +++ b/src/main/java/com/boot/security/server/service/impl/RoleServiceImpl.java @@ -0,0 +1,67 @@ +package com.boot.security.server.service.impl; + +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; + +import com.boot.security.server.dao.RoleDao; +import com.boot.security.server.dto.RoleDto; +import com.boot.security.server.model.Role; +import com.boot.security.server.service.RoleService; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j(topic = "adminLogger") +@Service +public class RoleServiceImpl implements RoleService { + + @Autowired + private RoleDao roleDao; + + @Override + @Transactional + public void saveRole(RoleDto roleDto) { + Role role = roleDto; + + if (role.getId() != null) {// 修改 + Role r = roleDao.getRole(role.getName()); + if (r != null && r.getId() != role.getId()) { + throw new IllegalArgumentException(role.getName() + "已存在"); + } + + roleDao.update(role); + } else {// 新增 + Role r = roleDao.getRole(role.getName()); + if (r != null) { + throw new IllegalArgumentException(role.getName() + "已存在"); + } + + roleDao.save(role); + + log.debug("新增角色{}", role.getName()); + } + + saveRolePermission(role.getId(), roleDto.getPermissionIds()); + } + + private void saveRolePermission(Long roleId, List permissionIds) { + roleDao.deleteRolePermission(roleId); + permissionIds.remove(0L); + if (!CollectionUtils.isEmpty(permissionIds)) { + roleDao.saveRolePermission(roleId, permissionIds); + } + } + + @Override + @Transactional + public void deleteRole(Long id) { + roleDao.deleteRolePermission(id); + roleDao.delete(id); + + log.debug("删除角色id:{}", id); + } + +} diff --git a/src/main/java/com/boot/security/server/service/impl/UserDetailsServiceImpl.java b/src/main/java/com/boot/security/server/service/impl/UserDetailsServiceImpl.java index 2e594e1..b729981 100644 --- a/src/main/java/com/boot/security/server/service/impl/UserDetailsServiceImpl.java +++ b/src/main/java/com/boot/security/server/service/impl/UserDetailsServiceImpl.java @@ -3,6 +3,10 @@ package com.boot.security.server.service.impl; import java.util.HashSet; import java.util.Set; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.authentication.AuthenticationCredentialsNotFoundException; +import org.springframework.security.authentication.DisabledException; +import org.springframework.security.authentication.LockedException; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.User; @@ -11,20 +15,36 @@ import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Service; +import com.boot.security.server.model.SysUser; +import com.boot.security.server.model.SysUser.Status; +import com.boot.security.server.service.UserService; + import lombok.extern.slf4j.Slf4j; @Slf4j @Service public class UserDetailsServiceImpl implements UserDetailsService { + @Autowired + private UserService userService; + @Override public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException { log.info(username); + SysUser sysUser = userService.getUser(username); + if (sysUser == null) { + throw new AuthenticationCredentialsNotFoundException("用户名不存在"); + } else if (sysUser.getStatus() == Status.LOCKED) { + throw new LockedException("用户被锁定"); + } else if (sysUser.getStatus() == Status.DISABLED) { + throw new DisabledException("用户已作废"); + } + Set authorities = new HashSet<>(); GrantedAuthority grantedAuthority = new SimpleGrantedAuthority("rrr"); authorities.add(grantedAuthority); - User user = new User(username, username, authorities); + User user = new User(username, sysUser.getPassword(), authorities); return user; } diff --git a/src/main/java/com/boot/security/server/service/impl/UserServiceImpl.java b/src/main/java/com/boot/security/server/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..2004f49 --- /dev/null +++ b/src/main/java/com/boot/security/server/service/impl/UserServiceImpl.java @@ -0,0 +1,84 @@ +package com.boot.security.server.service.impl; + +import java.util.List; +import java.util.UUID; + +import org.apache.commons.codec.digest.DigestUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; + +import com.boot.security.server.dao.UserDao; +import com.boot.security.server.dto.UserDto; +import com.boot.security.server.model.SysUser; +import com.boot.security.server.model.SysUser.Status; +import com.boot.security.server.service.UserService; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j(topic = "adminLogger") +@Service +public class UserServiceImpl implements UserService { + + @Autowired + private UserDao userDao; + @Autowired + private BCryptPasswordEncoder passwordEncoder; + + @Override + @Transactional + public SysUser saveUser(UserDto userDto) { + SysUser user = userDto; + user.setSalt(DigestUtils + .md5Hex(UUID.randomUUID().toString() + System.currentTimeMillis() + UUID.randomUUID().toString())); + user.setPassword(passwordEncoder.encode(user.getPassword())); + user.setStatus(Status.VALID); + userDao.save(user); + saveUserRoles(user.getId(), userDto.getRoleIds()); + + log.debug("新增用户{}", user.getUsername()); + return user; + } + + private void saveUserRoles(Long userId, List roleIds) { + if (roleIds != null) { + userDao.deleteUserRole(userId); + if (!CollectionUtils.isEmpty(roleIds)) { + userDao.saveUserRoles(userId, roleIds); + } + } + } + + @Override + public SysUser getUser(String username) { + return userDao.getUser(username); + } + + @Override + public void changePassword(String username, String oldPassword, String newPassword) { + SysUser u = userDao.getUser(username); + if (u == null) { + throw new IllegalArgumentException("用户不存在"); + } + + if (!passwordEncoder.matches(newPassword, u.getPassword())) { + throw new IllegalArgumentException("密码错误"); + } + + userDao.changePassword(u.getId(), passwordEncoder.encode(newPassword)); + + log.debug("修改{}的密码", username); + } + + @Override + @Transactional + public SysUser updateUser(UserDto userDto) { + userDao.update(userDto); + saveUserRoles(userDto.getId(), userDto.getRoleIds()); + + return userDto; + } + +}