如何解决Spring Security 问题?

1u4esq0p  于 2021-07-23  发布在  Java
关注(0)|答案(2)|浏览(328)

我无法以具有此角色的用户身份登录到我的应用程序 admin 或者作为角色的用户 user . 我总是以用户身份登录 anonymous .

Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public PasswordEncoder encoder() {
        return new StandardPasswordEncoder("53cr3t");
    }
    @Autowired
    UserDetailsServiceImpl userDetailsService;

    public SecurityConfig(UserDetailsServiceImpl userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }

    @Bean
    public DaoAuthenticationProvider authProvider() {
        DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();

        authProvider.setUserDetailsService(userDetailsService);
        authProvider.setPasswordEncoder(encoder());

        return authProvider;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()

        .authorizeRequests()

                .antMatchers("/").authenticated()
                .antMatchers("/rentAppPage/").hasRole("ADMIN")
                .antMatchers("/addVehicle").hasRole("ADMIN")
                .antMatchers("/getVehicle").hasRole("ADMIN")
                .antMatchers("/removeVehicle").hasRole("ADMIN")
                .antMatchers("/updateVehicle").hasRole("ADMIN")
                .antMatchers("/allUser").hasRole("ADMIN")
                .antMatchers("/resultGet").hasRole("ADMIN")
                .antMatchers("/addUser").hasRole("ADMIN")
                .antMatchers("/getUser").hasRole("ADMIN")
                .antMatchers("/updateUser").hasRole("ADMIN")
                .antMatchers("/removeUserById").hasRole("ADMIN")
                .antMatchers("/price").hasAnyAuthority("ROLE_ADMIN", "ROLE_USER")
                .antMatchers("/allScooter").hasAnyAuthority( "ROLE_ADMIN", "ROLE_USER")
                .antMatchers("/allCar").hasAnyAuthority( "ROLE_ADMIN", "ROLE_USER")
                .antMatchers("/allMotorBike").hasAnyAuthority( "ROLE_ADMIN", "ROLE_USER")
                .antMatchers("/allBike").hasAnyAuthority("ROLE_USER", "ROLE_ADMIN")
                .antMatchers("/distance").hasAnyAuthority("ROLE_USER", "ROLE_ADMIN")
                .antMatchers("/user").hasAnyAuthority( "ROLE_ADMIN", "ROLE_USER")
                .antMatchers("/rent").hasAnyAuthority( "ROLE_ADMIN", "ROLE_USER")
                .antMatchers("/rent2").hasAnyAuthority( "ROLE_ADMIN", "ROLE_USER")
                .antMatchers("/buy").hasAnyAuthority( "ROLE_ADMIN", "ROLE_USER")
                .antMatchers("/buy2").hasAnyAuthority( "ROLE_ADMIN", "ROLE_USER")
                .antMatchers("/thanks").hasAnyAuthority( "ROLE_ADMIN", "ROLE_USER")
                .antMatchers("/rentAppPage").hasAnyAuthority( "ROLE_ADMIN", "ROLE_USER")
                .and()
                .formLogin()

                .defaultSuccessUrl("/", true)
                .and()
                .logout()
                 .logoutSuccessUrl("/");
        ;

        http.sessionManagement()
                //.expiredUrl("/sessionExpired.html")
                .invalidSessionUrl("/login.html");
    }

}
@Entity
@Table(name = "user")
public class User  {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int idUser;

    private String username;
    private String password;
    private String name;
    private String surname;
    private String email;
    private double latitude;
    private double longitude;
    private String role;
    private String locationName;
}
@Slf4j
@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    IUserDAO userDAO;

    public UserDetailsServiceImpl(IUserDAO userDAO){
        this.userDAO = userDAO;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user  = userDAO.findByUsername(username);
        if(user == null){
            throw  new UsernameNotFoundException("User dont exist");
        }
        return new MyUserDetails(user);
    }
}
@Repository
public class UserDAOImpl implements IUserDAO {

    @Autowired
    SessionFactory sessionFactory;

    public UserDAOImpl(SessionFactory sessionFactory){
        this.sessionFactory = sessionFactory;
    }

    @Override
    public void addUser(User user){
        Session session = null;
        Transaction tx = null;

        try{
            session = this.sessionFactory.openSession();
            tx = session.beginTransaction();
            session.save(user);
            tx.commit();
        }catch (HibernateException e){
            if(tx != null)tx.rollback();
        }finally {
            session.close();
        }
    }

    @Override
    public User findByUsername(String username) {
        Session  session = this.sessionFactory.openSession();
        User user =(User) session.createQuery("FROM pl.edu.wszib.model.User WHERE username = :username" )
                .setParameter("username", username)
                .uniqueResult();
        session.close();
        return user;

    }
}
public class MyUserDetails implements UserDetails {

    private User user;

    public MyUserDetails(User user) {
        this.user = user;
    }

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        SimpleGrantedAuthority authority = new SimpleGrantedAuthority(user.getRole());
        return Arrays.asList(authority);
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        return user.getUsername();
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

}
2021-01-18 17:05:43.545 DEBUG 4256 --- [io-8080-exec-10] o.s.s.w.a.AnonymousAuthenticationFilter  : Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@cd98cfcc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@0: RemoteIpAddress: 127.0.0.1; SessionId: AD82C9600EFB66CF7C6F8A1BCCEEAE0D; Granted Authorities: ROLE_ANONYMOUS'

我在mysql数据库中有两个用户第一个角色admin第二个角色user我在数据库中的角色是role\u admin,role\u user我的完整代码在这里https://github.com/conrado1212/springsecuritywhycantworkfine 有人能解释为什么我不能以管理员或用户的身份登录应用程序吗?

r6l8ljro

r6l8ljro1#

当然,关于编码器、md5等有很多问题,但这是你的选择(即使它是错的)
我运行你的代码,如果md5哈希是正确的数据库我可以登录。据我所知,问题是为什么应用程序不存储登录用户的状态?
期望值:
第一个请求:call method(incognito)->login->call method(authorized)
第x个请求:call method->spring security checks->call method(authorized)
现实:
第X个请求:始终等于第1个
原因是您没有更改spring安全上下文的状态。调用/登录端点,检查用户是否在db中,检查其密码并返回成功响应。您应该创建一个授权并将其放置在spring安全上下文中。
简单示例:

UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken =
    new UsernamePasswordAuthenticationToken(username, password);
Authentication authentication = authenticationManager.authenticate(usernamePasswordAuthenticationToken);
SecurityContextHolder.getContext().setAuthentication(authentication);
String token = tokenProvider.generateToken(authentication);
return token;

在接下来的请求中使用令牌。如何实现令牌提供者有很多例子。它可以是定制的或更好的jwt。
如果您不需要令牌(restful),可以在请求中使用会话(untinent),但它需要额外的配置。

jmp7cifd

jmp7cifd2#

查看了您在github上发布的代码,您在上述问题中发布的代码都不是问题所在。您的问题是如何执行您的登录。
登录.html

<form action="/authenticate" method="post" id="login" class="input-group">
     <div th:text="`enter code here`${errorMessage}" id="error-message"></div>
    <input type="text" class="input-field" placeholder="Enter username" name="username" th:field="*{userModel.username}"  required>
    <input type="password" class="input-field" placeholder="Enter password"  name="password" th:field="*{userModel.password}"required>
    <input type="checkbox" class="chech-box"><span class="span1">Remember password</span>
    <button type="submit" class="submit-btn">Log in</button>
</form>

在这里,我们假设登录表单发布到端点 /authenticate . 这不是标准 /login spring security自动为您设置的端点。
因为您没有使用标准,所以我找到了您的自定义端点。
登录控制器.java

@RequestMapping(value = "/authenticate",method = RequestMethod.POST)
public  String authenticateUser(@ModelAttribute("userModel")User user,Model model){
    boolean authResult = this.authenticationService.authenticationUser(user);
    if(authResult){
        System.out.println("zalogowano !!");
        return "rentAppPage";
    } else {
        model.addAttribute("errorMessage","zle dane!!!");
        model.addAttribute("userModel",new User());
        return "login";
    }
}

在这里,我们看到您将user对象传递到一个名为 authenticationUser . 因此,如果我们查看该函数,就会发现这个实现。
authenticationservice.java

@Override
public boolean authenticationUser(User user){
    User userFromDb = this.userDAO.findByUsername(user.getUsername());
    return userFromDb != null && userFromDb.getPassword().equals(DigestUtils.md5Hex(user.getPassword()));
}

在这个函数中,您所做的就是从数据库中获取用户。检查用户密码是否匹配,然后返回布尔值。
如果布尔值为真,则返回下一页。
这不是SpringSecurity的工作方式。上面所有的代码都是完全错误的,很明显,在这里询问堆栈溢出之前还没有做过任何研究。服务器怎么知道你以前调用过这个函数?不可能。
我对你的问题的回答是,你的实现是完全错误的,我强烈建议你找一个 getting started guide 对于表单登录如何在spring安全中工作,因为解释spring安全如何工作,不能用简单的答案来回答。
我要做的就是把你和官方联系起来 Spring security FormLogin 文档,你应该开始阅读。

相关问题