diff --git a/build.gradle b/build.gradle index b7a38ef..30dd5a8 100644 --- a/build.gradle +++ b/build.gradle @@ -31,6 +31,9 @@ dependencies { testImplementation 'io.projectreactor:reactor-test' testImplementation 'org.springframework.security:spring-security-test' compile group: 'io.springfox', name: 'springfox-boot-starter', version: '3.0.0' + + implementation 'com.aiprose:jpa-common-utils:2.3.4' + implementation 'org.apache.commons:commons-lang3:3.10' } test { diff --git a/src/main/java/com/aiprose/scauth/conf/WebSecurityConfig.java b/src/main/java/com/aiprose/scauth/conf/WebSecurityConfig.java index cd433d2..3abb4e2 100644 --- a/src/main/java/com/aiprose/scauth/conf/WebSecurityConfig.java +++ b/src/main/java/com/aiprose/scauth/conf/WebSecurityConfig.java @@ -1,18 +1,24 @@ package com.aiprose.scauth.conf; +import com.aiprose.scauth.entity.User; import com.aiprose.scauth.handler.AuthLimitHandler; import com.aiprose.scauth.handler.LoginSuccessHandler; +import com.aiprose.scauth.service.IUserService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; 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.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; /** * @author nelson - * @desc TODO + * @desc script配置 * @company 北京中经网软件有限公司 * @date 2020/11/27 15:32 * @since 1.0 @@ -20,6 +26,9 @@ import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; @Configuration @EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true, jsr250Enabled = true) public class WebSecurityConfig extends WebSecurityConfigurerAdapter { + @Autowired + private IUserService userService; + @Override public void configure(WebSecurity web) throws Exception { // super.configure(web); @@ -27,22 +36,42 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { - super.configure(http); + http.csrf().disable(); + +// http.authorizeRequests().antMatchers("/user/save").permitAll().anyRequest(); + http.formLogin().successHandler(new LoginSuccessHandler()); //权限不足 http.exceptionHandling().accessDeniedHandler(new AuthLimitHandler()); + super.configure(http); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { - auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder()) - .withUser("nelson").password(new BCryptPasswordEncoder().encode("123456")).roles("admin") - .and() - .withUser("yasaka").password(new BCryptPasswordEncoder().encode("123456")).roles("user") - .and() - .withUser("one").password(new BCryptPasswordEncoder().encode("123456")).roles("gest") - .and() - .withUser("admin").password(new BCryptPasswordEncoder().encode("123456")).roles("root"); + auth.userDetailsService(userDetailsService()).passwordEncoder(new BCryptPasswordEncoder()); +// super.configure(auth); +// auth.passwordEncoder(new BCryptPasswordEncoder()); +// .withUser("nelson").password(new BCryptPasswordEncoder().encode("123456")).roles("admin") +// .and() +// .withUser("yasaka").password(new BCryptPasswordEncoder().encode("123456")).roles("user") +// .and() +// .withUser("one").password(new BCryptPasswordEncoder().encode("123456")).roles("gest") +// .and() +// .withUser("admin").password(new BCryptPasswordEncoder().encode("123456")).roles("root"); + } + + @Override + protected UserDetailsService userDetailsService() { + return username -> { + if(StringUtils.isBlank(username)){ + throw new UsernameNotFoundException("用户名为空"); + } + User user = userService.findByUsernameAndRole(username); + if(user == null){ + throw new UsernameNotFoundException("用户不存在"); + } + return user; + }; } } diff --git a/src/main/java/com/aiprose/scauth/controller/RoleController.java b/src/main/java/com/aiprose/scauth/controller/RoleController.java new file mode 100644 index 0000000..76860fd --- /dev/null +++ b/src/main/java/com/aiprose/scauth/controller/RoleController.java @@ -0,0 +1,36 @@ +package com.aiprose.scauth.controller; + +import com.aiprose.scauth.entity.Role; +import com.aiprose.scauth.entity.User; +import com.aiprose.scauth.entity.UserRole; +import com.aiprose.scauth.service.IRoleService; +import com.aiprose.scauth.service.IUserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author nelson + * @desc TODO + * @company 北京中经网软件有限公司 + * @date 2020/11/27 17:21 + * @since 1.0 + */ +@RestController() +@RequestMapping("role") +public class RoleController { + + @Autowired + private IRoleService roleService; + + // roleName 必须要有ROLE_前缀 + @PostMapping("save") + public UserRole save(String roleName,Integer userId){ + Role role = new Role(); + role.setRole(roleName); + UserRole userRole = roleService.save(role,userId); + return userRole; + } +} diff --git a/src/main/java/com/aiprose/scauth/controller/UserController.java b/src/main/java/com/aiprose/scauth/controller/UserController.java new file mode 100644 index 0000000..af5e2a2 --- /dev/null +++ b/src/main/java/com/aiprose/scauth/controller/UserController.java @@ -0,0 +1,32 @@ +package com.aiprose.scauth.controller; + +import com.aiprose.scauth.entity.User; +import com.aiprose.scauth.service.IUserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author nelson + * @desc TODO + * @company 北京中经网软件有限公司 + * @date 2020/11/27 17:21 + * @since 1.0 + */ +@RestController() +@RequestMapping("user") +public class UserController { + + @Autowired + private IUserService userService; + + @PostMapping("save") + public User save(User user){ + String encode = new BCryptPasswordEncoder().encode(user.getPassword()); + user.setPassword(encode); + User save = userService.save(user); + return save; + } +} diff --git a/src/main/java/com/aiprose/scauth/entity/IDEntity.java b/src/main/java/com/aiprose/scauth/entity/IDEntity.java new file mode 100644 index 0000000..6f264bc --- /dev/null +++ b/src/main/java/com/aiprose/scauth/entity/IDEntity.java @@ -0,0 +1,18 @@ +package com.aiprose.scauth.entity; + +import lombok.Data; + +import javax.persistence.*; +import java.io.Serializable; + +@Data +@MappedSuperclass +public class IDEntity implements Serializable { + /** + * 主键 + */ + @Id + @Column(columnDefinition = "INT UNSIGNED") + @GeneratedValue(strategy = GenerationType.AUTO) + protected Integer id; +} \ No newline at end of file diff --git a/src/main/java/com/aiprose/scauth/entity/Role.java b/src/main/java/com/aiprose/scauth/entity/Role.java new file mode 100644 index 0000000..7f24737 --- /dev/null +++ b/src/main/java/com/aiprose/scauth/entity/Role.java @@ -0,0 +1,26 @@ +package com.aiprose.scauth.entity; + +import lombok.Data; +import org.springframework.security.core.GrantedAuthority; + +import javax.persistence.Entity; +import javax.persistence.Table; + +/** + * @author nelson + * @desc 角色表 + * @company 北京中经网软件有限公司 + * @date 2020/11/27 17:04 + * @since 1.0 + */ +@Data +@Entity +@Table(name="sys_role") +public class Role extends IDEntity implements GrantedAuthority { + private String role; + + @Override + public String getAuthority() { + return role; + } +} diff --git a/src/main/java/com/aiprose/scauth/entity/User.java b/src/main/java/com/aiprose/scauth/entity/User.java new file mode 100644 index 0000000..d37995a --- /dev/null +++ b/src/main/java/com/aiprose/scauth/entity/User.java @@ -0,0 +1,56 @@ +package com.aiprose.scauth.entity; + +import lombok.Data; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.Table; +import javax.persistence.Transient; +import java.util.Collection; +import java.util.List; + +/** + * @author nelson + * @desc 用户表 + * @company 北京中经网软件有限公司 + * @date 2020/11/27 17:04 + * @since 1.0 + */ +@Data +@Entity +@Table(name="sys_user") +public class User extends IDEntity implements UserDetails { + @Column(unique = true) + private String username; + private String password; + + @Transient + private List roles; + + @Override + public Collection getAuthorities() { + return roles; + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } +} diff --git a/src/main/java/com/aiprose/scauth/entity/UserRole.java b/src/main/java/com/aiprose/scauth/entity/UserRole.java new file mode 100644 index 0000000..4303ab2 --- /dev/null +++ b/src/main/java/com/aiprose/scauth/entity/UserRole.java @@ -0,0 +1,22 @@ +package com.aiprose.scauth.entity; + +import lombok.Data; + +import javax.persistence.Entity; +import javax.persistence.Table; + +/** + * @author nelson + * @desc 用户角色关联表 + * @company 北京中经网软件有限公司 + * @date 2020/11/27 17:04 + * @since 1.0 + */ +@Data +@Entity +@Table(name="sys_user_role") +public class UserRole extends IDEntity{ + private Integer sysUserId; + private Integer sysRoleId; + +} diff --git a/src/main/java/com/aiprose/scauth/repository/RoleRepository.java b/src/main/java/com/aiprose/scauth/repository/RoleRepository.java new file mode 100644 index 0000000..73559e4 --- /dev/null +++ b/src/main/java/com/aiprose/scauth/repository/RoleRepository.java @@ -0,0 +1,15 @@ +package com.aiprose.scauth.repository; + +import com.aiprose.scauth.entity.Role; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +/** + * @author nelson + * @desc TODO + * @company 北京中经网软件有限公司 + * @date 2020/11/27 17:17 + * @since 1.0 + */ +public interface RoleRepository extends JpaRepository, JpaSpecificationExecutor { +} diff --git a/src/main/java/com/aiprose/scauth/repository/UserRepository.java b/src/main/java/com/aiprose/scauth/repository/UserRepository.java new file mode 100644 index 0000000..d241afe --- /dev/null +++ b/src/main/java/com/aiprose/scauth/repository/UserRepository.java @@ -0,0 +1,17 @@ +package com.aiprose.scauth.repository; + +import com.aiprose.scauth.entity.User; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +/** + * @author nelson + * @desc TODO + * @company 北京中经网软件有限公司 + * @date 2020/11/27 17:17 + * @since 1.0 + */ +public interface UserRepository extends JpaRepository, JpaSpecificationExecutor { + + User findByUsername(String username); +} diff --git a/src/main/java/com/aiprose/scauth/repository/UserRoleRepository.java b/src/main/java/com/aiprose/scauth/repository/UserRoleRepository.java new file mode 100644 index 0000000..08ca177 --- /dev/null +++ b/src/main/java/com/aiprose/scauth/repository/UserRoleRepository.java @@ -0,0 +1,19 @@ +package com.aiprose.scauth.repository; + +import com.aiprose.scauth.entity.Role; +import com.aiprose.scauth.entity.UserRole; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +import java.util.List; + +/** + * @author nelson + * @desc TODO + * @company 北京中经网软件有限公司 + * @date 2020/11/27 17:17 + * @since 1.0 + */ +public interface UserRoleRepository extends JpaRepository, JpaSpecificationExecutor { + List findBySysUserId(Integer userId); +} diff --git a/src/main/java/com/aiprose/scauth/service/IRoleService.java b/src/main/java/com/aiprose/scauth/service/IRoleService.java new file mode 100644 index 0000000..eb87a14 --- /dev/null +++ b/src/main/java/com/aiprose/scauth/service/IRoleService.java @@ -0,0 +1,20 @@ +package com.aiprose.scauth.service; + +import com.aiprose.base.BaseSpecService; +import com.aiprose.scauth.entity.Role; +import com.aiprose.scauth.entity.UserRole; + +import java.util.List; + +/** + * @author nelson + * @desc TODO + * @company 北京中经网软件有限公司 + * @date 2020/11/27 17:23 + * @since 1.0 + */ +public interface IRoleService extends BaseSpecService { + List findByUserId(Integer userId); + + UserRole save(Role role, Integer userId); +} diff --git a/src/main/java/com/aiprose/scauth/service/IUserService.java b/src/main/java/com/aiprose/scauth/service/IUserService.java new file mode 100644 index 0000000..f945864 --- /dev/null +++ b/src/main/java/com/aiprose/scauth/service/IUserService.java @@ -0,0 +1,16 @@ +package com.aiprose.scauth.service; + +import com.aiprose.base.BaseSpecService; +import com.aiprose.scauth.entity.User; + +/** + * @author nelson + * @desc TODO + * @company 北京中经网软件有限公司 + * @date 2020/11/27 17:23 + * @since 1.0 + */ +public interface IUserService extends BaseSpecService { + User findByUsername(String username); + User findByUsernameAndRole(String username); +} diff --git a/src/main/java/com/aiprose/scauth/service/impl/RoleServiceImpl.java b/src/main/java/com/aiprose/scauth/service/impl/RoleServiceImpl.java new file mode 100644 index 0000000..3fd6e04 --- /dev/null +++ b/src/main/java/com/aiprose/scauth/service/impl/RoleServiceImpl.java @@ -0,0 +1,54 @@ +package com.aiprose.scauth.service.impl; + +import com.aiprose.base.BaseSpecServiceImpl; +import com.aiprose.scauth.entity.Role; +import com.aiprose.scauth.entity.UserRole; +import com.aiprose.scauth.repository.RoleRepository; +import com.aiprose.scauth.repository.UserRoleRepository; +import com.aiprose.scauth.service.IRoleService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author nelson + * @desc TODO + * @company 北京中经网软件有限公司 + * @date 2020/11/27 17:22 + * @since 1.0 + */ +@Service +@Transactional +public class RoleServiceImpl extends BaseSpecServiceImpl implements IRoleService { + + @Autowired + private UserRoleRepository userRoleRepository; + + @Override + public List findByUserId(Integer userId) { + List userRoles = userRoleRepository.findBySysUserId(userId); + if (userRoles == null) { + return new ArrayList<>(); + } + List roleIds = userRoles.stream().map(x -> x.getSysRoleId()).collect(Collectors.toList()); + List allById = repository.findAllById(roleIds); + if (allById != null) { + return allById; + } + return new ArrayList<>(); + } + + @Override + public UserRole save(Role role, Integer userId) { + Role newRole = repository.save(role); + UserRole userRole = new UserRole(); + userRole.setSysUserId(userId); + userRole.setSysRoleId(newRole.getId()); + UserRole save = userRoleRepository.save(userRole); + return save; + } +} diff --git a/src/main/java/com/aiprose/scauth/service/impl/UserServiceImpl.java b/src/main/java/com/aiprose/scauth/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..09f250f --- /dev/null +++ b/src/main/java/com/aiprose/scauth/service/impl/UserServiceImpl.java @@ -0,0 +1,43 @@ +package com.aiprose.scauth.service.impl; + +import com.aiprose.base.BaseSpecServiceImpl; +import com.aiprose.scauth.entity.Role; +import com.aiprose.scauth.entity.User; +import com.aiprose.scauth.repository.UserRepository; +import com.aiprose.scauth.service.IRoleService; +import com.aiprose.scauth.service.IUserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.List; + +/** + * @author nelson + * @desc TODO + * @company 北京中经网软件有限公司 + * @date 2020/11/27 17:22 + * @since 1.0 + */ +@Service +@Transactional +public class UserServiceImpl extends BaseSpecServiceImpl implements IUserService { + + @Autowired + private IRoleService roleService; + + @Override + public User findByUsername(String username) { + return repository.findByUsername(username); + } + + @Override + public User findByUsernameAndRole(String username) { + User byUsername = repository.findByUsername(username); + if(byUsername!=null){ + List byUserId = roleService.findByUserId(byUsername.getId()); + byUsername.setRoles(byUserId); + } + return byUsername; + } +}