美文网首页
一、工作流 Activiti7-13.SpringSecurit

一、工作流 Activiti7-13.SpringSecurit

作者: 那钱有着落吗 | 来源:发表于2021-04-07 09:11 被阅读0次
    image.png image.png

    1.实战

    首先我们需要新增这么个依赖,当然如果已经引用了Activiti7的话,是默认带有的

    <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
            </dependency>
    

    然后启动项目,在控制台是有一个密码的:


    image.png

    把这个复制好,然后再打开项目地址,就会有提示要输入账号密码,我们输入:
    user 刚赋值的密码,就可以登录访问接口了。

    我们再模拟一下登录:
    我们实现UserDetailsService类,然后重写该方法,写死正确的密码111,然后重启,发现用户名什么都行,密码一定要是111才可以验证成功,至于为什么这里可以写死密码,可以自定debug看源码就知道了(大概就是Security可以自己拿到输入框的密码,然后与该方法传入密码对比)

    @Configuration
    public class UserDetailsServiceImpl implements UserDetailsService {
    
        @Override
        public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
            String password = passwordEncoder().encode("111");
    
            return new User(userName,password,
                    AuthorityUtils.commaSeparatedStringToAuthorityList("ROLE_ACTIVITI_USER"));
        }
    
        @Bean
        public PasswordEncoder passwordEncoder(){
            return new BCryptPasswordEncoder();
        }
    }
    

    下面我们实现从数据库读取用户,然后可以成功登陆:

    
    @Data
    @Component
    public class UserInfo implements UserDetails {
    
    
        private Long id;
        private String name;
        private String username;
        private String password;
        private String address;
        private String roles;
    
        private String getAddress(){
            return address;
        }
    
        /**
         * Returns the authorities granted to the user. Cannot return <code>null</code>.
         *
         * @return the authorities, sorted by natural key (never <code>null</code>)
         */
        @Override
        public Collection<? extends GrantedAuthority> getAuthorities() {
            return Arrays.stream(roles.split(",")).map(s -> new SimpleGrantedAuthority(s)).collect(Collectors.toList());
        }
    
        /**
         * Returns the password used to authenticate the user.
         *
         * @return the password
         */
        @Override
        public String getPassword() {
            return password;
        }
    
        /**
         * Returns the username used to authenticate the user. Cannot return
         * <code>null</code>.
         *
         * @return the username (never <code>null</code>)
         */
        @Override
        public String getUsername() {
            return username;
        }
    
        /**
         * Indicates whether the user's account has expired. An expired account cannot be
         * authenticated.
         *
         * @return <code>true</code> if the user's account is valid (ie non-expired),
         * <code>false</code> if no longer valid (ie expired)
         */
        @Override
        public boolean isAccountNonExpired() {
            return true;
        }
    
        /**
         * Indicates whether the user is locked or unlocked. A locked user cannot be
         * authenticated.
         *
         * @return <code>true</code> if the user is not locked, <code>false</code> otherwise
         */
        @Override
        public boolean isAccountNonLocked() {
            return true;
        }
    
        /**
         * Indicates whether the user's credentials (password) has expired. Expired
         * credentials prevent authentication.
         *
         * @return <code>true</code> if the user's credentials are valid (ie non-expired),
         * <code>false</code> if no longer valid (ie expired)
         */
        @Override
        public boolean isCredentialsNonExpired() {
            return true;
        }
    
        /**
         * Indicates whether the user is enabled or disabled. A disabled user cannot be
         * authenticated.
         *
         * @return <code>true</code> if the user is enabled, <code>false</code> otherwise
         */
        @Override
        public boolean isEnabled() {
            return true;
        }
    }
    

    上面对应的是数据库中的user表,这个user表在本系列课程前面导入过一次,不了解的可以翻翻。

    创建一个根据用户名查询用户的方法:

    @Service
    public class UserService {
    
        @Autowired
        private JdbcTemplate jdbcTemplate;
    
        //根据用户名查询用户
        public UserInfo findByUserName(String userName){
            return jdbcTemplate.queryForObject("select * from user where username='"+userName+"'",
                    BeanPropertyRowMapper.newInstance(UserInfo.class));
        }
    }
    
     @Override
        public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
            UserInfo userInfo = userService.findByUserName(userName);
            if(userInfo==null){
                throw  new UsernameNotFoundException("数据库中没有此用户");
            }
            return userInfo;
        }
    

    这样做就是从数据库中把用户给查询出来然后验证登录了。

    2.登录接口配置

    首先我们需要编写登录配置信息

    @Configuration
    public class ActivitySecurityConfig extends WebSecurityConfigurerAdapter {
    
        @Autowired
        private LoginSuccessHandler loginSuccessHandler;
    
        @Override
        protected void configure(HttpSecurity httpSecurity) throws Exception{
            httpSecurity.formLogin()
                    .loginPage("/login")
                    .successHandler(loginSuccessHandler)
                    .and()
                    .authorizeRequests()
                    .anyRequest().permitAll().and().logout().permitAll()
                    .and().csrf().disable().headers().frameOptions().disable();
        }
    }
    

    在配置中,我们制定loginPage,这个可以指定页面或者方法,上面我们指定了方法,意思就是访问login这个接口就会走Security框架的登录验证。
    successHandler 我们填写的是注入的loginSuccessHandler类,其他的都是开放登录的配置,例如anyRequest().permitAll(),.logout().permitAll()都是允许登录登出的接口访问,csrf().disable().这个是允许ajax访问,frameOptions允许前端的frame框架登录。

    重写登录成功之后的方法处理

    @Component("loginSuccessHandler")
    public class LoginSuccessHandler implements AuthenticationSuccessHandler {
    
        //表单
        @Override
        public void onAuthenticationSuccess(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) throws IOException, ServletException {
            httpServletResponse.setContentType("application/json;charset=UTF-8");
            httpServletResponse.getWriter().write("登录成功LoginSuccessHandler");
        }
    
        //ajax
        @Override
        public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) throws IOException, ServletException {
    
        }
    }
    
    

    这个时候我们在进行ajax发送请求认证,成功。


    image.png

    除了登录成功的处理方法,我们还需要处理登录失败的方法:

    @Component("loginFailureHandler")
    public class LoginFailureHandler implements AuthenticationFailureHandler {
    
        /**
         * Called when an authentication attempt fails.
         *
         * @param request   the request during which the authentication attempt occurred.
         * @param response  the response.
         * @param exception the exception which was thrown to reject the authentication
         */
        @Override
        public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write("登录失败,原因是:"+exception.getMessage());
        }
    }
    
    image.png image.png

    登录失败配置好之后,登录接口就可以在失败的时候给与良好的提示信息了。

    接下来,我们还需要配置一个未登录用户需要跳转的接口:

    @Slf4j
    @RestController
    public class ActivitySecurityController {
    
        @RequestMapping(path = "login")
        @ResponseStatus(code=HttpStatus.UNAUTHORIZED)
        public String requiredAuth(HttpServletRequest request, HttpServletResponse response) {
            return "需要登录,请使用login.html或发起POST登录请求!";
        }
    
    }
    
     @Override
        protected void configure(HttpSecurity httpSecurity) throws Exception{
            httpSecurity.formLogin()
                    .loginPage("/login")
                    .loginProcessingUrl("/login")
                    .successHandler(loginSuccessHandler)
                    .failureHandler(loginFailureHandler)
                    .and()
                    .authorizeRequests()
                    .antMatchers("/login").permitAll()
                    .anyRequest().authenticated().and().logout().permitAll()
                    .and().csrf().disable().headers().frameOptions().disable();
        }
    

    这样的话,如果没有登录就会跳转到统一的页面进行提示了。

    在实际开发中可以通过判断请求的来源,如果是表单的话就可以提示跳转到登录页面,如果是ajax就提示信息即可。

    相关文章

      网友评论

          本文标题:一、工作流 Activiti7-13.SpringSecurit

          本文链接:https://www.haomeiwen.com/subject/hlbzcltx.html