我正在制作一个RESTFul API(不是web-app)并添加Spring Security性,但无法成功地做到这一点。
在浏览了stackoverflow上的大量文章和帖子之后,我终于发表了我的问题。请仔细检查一下,让我知道我错过了什么或者配置错误了什么?
基本实体
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
abstract class BaseEntity implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name = "ID", nullable = false, updatable = false)
private Long ID;
@CreatedBy
@Column(name = "CreatedBy", nullable = false, updatable = false)
private String createdBy;
@CreatedDate
@Column(name = "CreatedDate", nullable = false, updatable = false)
private LocalDateTime createdDate;
@LastModifiedBy
@Column(name = "ModifiedBy")
private String modifiedBy;
@LastModifiedDate
@Column(name = "ModifiedDate")
private LocalDateTime modifiedDate;
...getters setters
}
@Entity
@Table(name = "ROLE")
public class Role extends BaseEntity {
@Column(name = "Name")
private String name;
...getters setters
}
@Entity
@Table(name = "USER")
public class User extends BaseEntity {
@Column(name = "EmiratesID", unique = true, nullable = false, updatable = false)
private String emiratesID;
@Column(name = "FirstName")
private String firstName;
@Column(name = "LastName")
private String lastName;
@Column(name = "StaffID", unique = true, nullable = false, updatable = false)
private String staffID;
@Column(name = "Email", unique = true, nullable = false)
private String email;
@Column(name = "Password", nullable = false)
private String password;
@ManyToOne(optional = false, cascade = CascadeType.MERGE)
@JoinColumn(name = "ROLE_ID")
private Role role;
...getters setters
public UserDetails currentUserDetails() {
return CurrentUserDetails.create(this);
}
}
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final DataSource dataSource;
private final UserDetailsServiceImplementation userDetailsService;
@Autowired
public SecurityConfig(final DataSource dataSource, final UserDetailsServiceImplementation userDetailsService) {
this.dataSource = dataSource;
this.userDetailsService = userDetailsService;
}
@Bean
BCryptPasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception {
httpSecurity.authorizeRequests()
.antMatchers("/console/**").permitAll()
.antMatchers("/", "/greetUser", "/register", "/login").permitAll()
.antMatchers("/user/**").hasAnyAuthority(ROLES.USER.getValue(), ROLES.ADMIN.getValue())
.antMatchers("/admin/**").hasAuthority(ROLES.ADMIN.getValue()).anyRequest().authenticated();
httpSecurity.csrf().disable();
// required to make H2 console work with Spring Security
httpSecurity.headers().frameOptions().disable();
}
@Autowired
public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Override
public void configure(WebSecurity webSecurity) {
webSecurity.ignoring().antMatchers("/resources/**", "/static/**", "/css/**", "/js/**", "/images/**");
}
public class CurrentUserDetails implements UserDetails {
private String ROLE_PREFIX = "ROLE_";
private Long userID;
private String emiratesID;
private String firstName;
private String lastName;
private String staffID;
private String email;
private String password;
private Role role;
public CurrentUserDetails(Long ID, String emiratesID, String firstName,
String lastName, String staffID, String email,
String password, Role role) {
super();
this.userID = ID;
this.emiratesID = emiratesID;
this.firstName = firstName;
this.lastName = lastName;
this.staffID = staffID;
this.email = email;
this.password = password;
this.role = role;
}
public Long getUserID() {
return userID;
}
public String getEmiratesID() {
return emiratesID;
}
public String getEmail() {
return this.email;
}
public Role getRole() {
return this.role;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> grantedAuthority = new ArrayList<>();
grantedAuthority.add(new SimpleGrantedAuthority(ROLE_PREFIX + role.getName()));
return grantedAuthority;
}
@Override
public String getPassword() {
return this.password;
}
@Override
public String getUsername() {
return this.email;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
/**
* Helper method to add all details of Current User into Security User Object
* @param user User
* @return UserDetails
*/
public static UserDetails create(User user) {
return new CurrentUserDetails(user.getID(), user.getEmiratesID(),
user.getFirstName(), user.getLastName(),
user.getStaffID(), user.getEmail(),
user.getPassword(), user.getRole());
}
}
UserDetailsService
@Component/@Service
public class UserDetailsServiceImplementation implements UserDetailsService {
private static final Logger userDetailsServiceImplementationLogger = LogManager.getLogger(UserDetailsServiceImplementation.class);
private final UserRepository userRepository;
@Autowired
public UserDetailsServiceImplementation(final UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if (StringUtils.isEmpty(username)) {
userDetailsServiceImplementationLogger.error("UserDetailsServiceImplementation.loadUserByUsername() :: FAILED");
throw new UsernameNotFoundException("UserName is not passed");
}
User userFound = userRepository.findByEmail(username);
if (userFound == null) {
userDetailsServiceImplementationLogger.error("No user found with given username = {}", username);
throw new UsernameNotFoundException("No user found with given username");
}
return userFound.currentUserDetails();
}
}
UserController类
@RestController
@RequestMapping(value = "/user")
public class UserController {
private static Logger userControllerLogger = LogManager.getLogger(UserController.class);
@Autowired
private PropertiesConfig propertiesConfig;
@Autowired
private UserManager userManager;
@RequestMapping(value = "/listAll", method = RequestMethod.GET)
public ResponseEntity<Map<String, Object>> getUsersList() {
userControllerLogger.info("UserController.getUsersList()[/listAll] :: method call ---- STARTS");
LinkedHashMap<String, Object> result = userManager.findAllUsers();
userControllerLogger.info("UserController.getUsersList()[/listAll] :: method call ---- ENDS");
return new ResponseEntity<>(result, HttpStatus.OK);
}
}
AdminContrller类
@RestController
@RequestMapping(value = "/admin")
public class AdminController {
private static final Logger adminControllerLogger = LogManager.getLogger(AdminController.class);
private final PropertiesConfig propertiesConfig;
private final UserManager userManager;
@Autowired
public AdminController(final PropertiesConfig propertiesConfig, final UserManager userManager) {
this.propertiesConfig = propertiesConfig;
this.userManager = userManager;
}
@RequestMapping(value = "/home", method = {RequestMethod.GET})
public ResponseEntity<String> adminPortal(@RequestBody String adminName) {
adminControllerLogger.info("AdminController.adminPortal()[/home] :: method call ---- STARTS");
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
UserDTO adminUser = userManager.findUserByEmail(auth.getName());
if (adminUser == null) {
throw new UsernameNotFoundException(propertiesConfig.getProperty(ApplicationProperties.Messages.NO_USER_FOUND.getValue()));
}
adminControllerLogger.info("AdminController.adminPortal()[/home] :: method call ---- ENDS");
return new ResponseEntity<>(ApplicationConstants.GeneralConstants.WELCOME.getValue() + adminUser.getStaffID(), HttpStatus.OK);
}
}
尝试使用ROLE_USER/ADMIN和USER/ADMIN两个值
INSERT INTO ROLE(ID, CreatedBy, CreatedDate, ModifiedBy, ModifiedDate, Name) VALUES (-100, 'Muhammad Faisal Hyder', now(), '', null, 'ROLE_ADMIN'/'ADMIN')
INSERT INTO ROLE(ID, CreatedBy, CreatedDate, ModifiedBy, ModifiedDate, Name) VALUES (-101, 'Muhammad Faisal Hyder', now(), '', null, 'ROLE_USER'/'USER')
INSERT INTO USER(ID, CreatedBy, CreatedDate, ModifiedBy, ModifiedDate, EmiratesID, FirstName, LastName, Email, StaffID, Password, ROLE_ID) VALUES (-1, 'Muhammad Faisal Hyder', now(), '', null, 'ABCDEF12345', 'Muhammad Faisal', 'Hyder', 'faisal.hyder@gmail.com', 'S776781', '$2a$10$qr.SAgYewyCOh6gFGutaWOQcCYMFqSSpbVZo.oqsc428xpwoliu7C', -100)
INSERT INTO USER(ID, CreatedBy, CreatedDate, ModifiedBy, ModifiedDate, EmiratesID, FirstName, LastName, Email, StaffID, Password, ROLE_ID) VALUES (-2, 'Muhammad Faisal Hyder', now(), '', null, 'BCDEFG12345', 'John', 'Smith', 'John.Smith@gmail.com', 'S776741', '$2a$10$j9IjidIgwDfNGjNi8UhxAeLuoO8qgr/UH9W9.LmWJd/ohynhI7UJO', -101)
我附上了我认为有必要的所有可能的课程。请告诉我什么是问题。
我读过的文章;SO-1,SO-2,SO-3,SO-4,第1条,第2条
@dur感谢你的指出,也感谢其他人的有益见解。
1- Use ROLE_ in db entries.
2- Once prefix is added in db then no need to explicitly add this in
@Override
public Collection<? extends GrantedAuthority> getAuthorities(){...}
3- .and().httpBasic(); was missing from SpringSecurity configuration.
4- This is very detailed, might be helpful to others as well.
我看到的问题是,您授予了admin
权限,但您没有将此权限添加到CurrentUserDetails
中,您只是添加了他们的角色。您还应该添加权限,即。
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
List<GrantedAuthority> grantedAuthority = new ArrayList<>();
grantedAuthority.add(new SimpleGrantedAuthority(ROLE_PREFIX + role.getName()));
// add authority in addition to role (no role prefix)
grantedAuthority.add(new SimpleGrantedAuthority(role.getName()));
return grantedAuthority;
}
当我创建新用户或授予现有特权,我得到了这个错误: 授予所有表上的权限ok(信息\u架构除外),在此表上我得到了拒绝访问错误。我怎么能修理?转储所有数据库,删除所有数据库,然后从转储还原?
为什么当我试图创建InputStream时,下面的代码会给我一个File Not Found异常?我的inputdirectory定义为一个文件,其值为“D:\general\images\small_images”(不带引号),我的用户对该文件具有完全的写权限。我正在使用Windows7,并以管理员的身份运行eclipse IDE。 如有任何帮助,不胜感激。
我找到了商店定位器的谷歌教程:https://developers.google.com/maps/articles/phpsqlsearch_v3#findnearsql MySQL表完成了,它在我的服务器上工作。我可以在phpmyadmin中正确地写入地址和执行操作 但是在“用PHP输出XML”的教程中,我不能继续了。 我已经创建了文件phpsqlsearch_dbinfo.php,把我的数据
问题内容: 我有以下代码: 当我尝试保存文件时,出现以下错误 原因可能是什么,我该如何解决?我确实对此文件夹具有读写权限。 问题答案: 当创建一个new时,应该提供文件名,而不仅是要放置文件的目录。 尝试类似的东西
问题内容: 这是我的编辑从第27行到第39行的代码: 我认为我的问题可能与Win7教授有关:(访问被拒绝) 如何解决这个问题,或者我需要做些什么或阅读才能使它起作用? 谢谢你不燃烧。 我只是更改了文件夹选项,使我获得完整的(Access …),现在我只需要弄清楚为什么在运行javac VendingMachine.java时为什么没有得到任何输出,我想是有一个新问题。 问题答案: 您的工作目录为。
问题内容: 这是我的Java代码: 一个非常简单的任务,我尝试使用AmazonS3 Java客户端访问S3,但是此行不断失败,并给了我以下异常: 一个非常明显的错误代码:403,它表示我的AWS凭证是错误的,但是,这与我的同事用来访问同一s3存储桶的凭证完全相同,以排除我在某处出现错字的可能性,因此我确实删除了我以前的一个,并使用了我同事发送给我的那个,并将其放在〜/ .aws /下 我还研究了其
问题内容: 我正在尝试读取文件夹中的文件,但是当我运行该程序时,它将引发此异常。我也尝试了其他一些文件夹。它引发相同的异常。 问题答案: 您无法打开和读取目录,无法使用和方法区分文件和文件夹。您可以使用和方法获取文件夹的内容(分别用于文件名和s),还可以指定一个过滤器来选择列出的文件的子集。
我正在使用wamp服务器,我的phpMyAdmin页面返回了以下错误。 Wamp服务器版本:2.2 MySQL版本:5.5.24 #1045-用户“root”@“本地主机”的访问被拒绝(使用密码:是) 我编辑了我的配置文件wamp\app\phpmyadmin4.1.14\config.inc.php: 但这并没有解决问题。任何帮助都将不胜感激。